Forums / Developer / Sorting multiple classes by custom attribute

Sorting multiple classes by custom attribute

Author Message

lynn patchett

Wednesday 16 November 2005 4:24:54 am

Hi,

I have a number of classes which all have an attribute date_released which is a date object.

I am trying to retrieve the last 5 entries from any of these classes sorted by the date_released.

The code I am using is this:
{let recent=fetch( 'content', 'list', hash( 'parent_node_id', array(79,80,81,82,83,84,85,115), limit, 5, sort_by, array('attribute', false(), 'date_released') ) ) }

This however does not return a result. If I try the same query on just one class it also does not return a result.

The only way I have found so far to sort by the date_released attribute is using this:

{let recent=fetch( 'content', 'list', hash( 'parent_node_id', array(79,80,81,82,83,84,85,115), limit, 5, sort_by, array('attribute', false(), '186') ) ) }

Where 186 is the id of the date_released attribute in one specific class.
This however is not what i need as it only lists the contents of the one class.

I have read the documentation regarding sorting by custom attributes and if I understand correctly using the attribute name should work....but does not, only using the id of the desired attribute works.

Is this a bug? Am I doing something wrong... any ideas?

I am using ezpublish 3.6/3.7

Thanks
Lynn

lynn patchett

Wednesday 16 November 2005 5:20:19 am

So answering to myself, I was leaving out the class name attribute of the sort attribute name:

{let recent=fetch( 'content', 'list', hash( 'parent_node_id', array(79,80,81,82,83,84,85,115), limit, 5, sort_by, array('attribute', false(), 'class2/date_released') ) ) }

which is fine, but i need to sort by the date released on all the classes included in the parent_node_id array, someting like this:

{let recent=fetch( 'content', 'list', hash( 'parent_node_id', array(79,80,81,82,83,84,85,115), limit, 5, sort_by, array('attribute', false(), array('class1/date_released','class2/date_released') ) ) }

or something like that. Anyone know if this is possible?

Thanks
Lynn

lynn patchett

Thursday 30 March 2006 6:38:46 am

So, returning to this problem, i will bump the post.

Original problem still stands, I want to sort multiple classes all by a date datatype called 'date_released'. Every class has this datatype (with the same name), but of course they have different id numbers.

This should not be so hard to do! Am I missing something?

Surely sorting by custom attributes should not be restricted to one class if the attributes are of the same type? Seems to me that this is a problem that many would encounter... or maybe not....

Anyone?

Thanks

Kristof Coomans

Thursday 30 March 2006 6:52:56 am

I'm afraid that what you are trying to do is currently impossible with the content/list and content/tree fetch functions. It would be a nice feature though, so maybe you can add an enhancement request at http://ez.no/community/bugs.

independent eZ Publish developer and service provider | http://blog.coomanskristof.be | http://ezpedia.org

lynn patchett

Thursday 30 March 2006 7:14:08 am

Hi,

Thanks for the reply, although it was not wanted i was hoping to hear.

Any pointers as to why it is not possible? From what I understood from the documentaion, it seems possible, or at least is not explicitly deemed impossible. I will certainly add it to the enhancement list.

In the meantime, I am stuck with the same problem, 2 different classes need to display the last 10 from either class sorted by the date_released. Anybody have an idea of a work around which will point me in the right direction? Might it be possible to do 2 seperate selects, push the results into one array and then sort it?

Urgh, sounds complicated already.

Thanks.

Kristof Coomans

Thursday 30 March 2006 7:36:57 am

I think it's possible to make an extended attribute filter which can do this. But you will need some PHP programming skills to make that, and some knowledge of the eZ internals.

independent eZ Publish developer and service provider | http://blog.coomanskristof.be | http://ezpedia.org

Marc Boon

Friday 31 March 2006 5:42:17 am

The documentation says: "Attribute sorting can only be used if the returned collection contains the same type of nodes".
Which means the nodes have to be of the same class.

See: http://ez.no/doc/ez_publish/technical_manual/3_6/reference/modules/content/fetch_functions/list

lynn patchett

Friday 31 March 2006 6:12:29 am

yes, I guess I read that wrong then.

Still, I think that this is something that would be useful in many situations. I find it frustrating that something I could do with a quite simple mysql statement cannot be done from inside the ez system and I am inclined to add this as an enhancement request.

I will look into the advanced attribute filtering mentioned above, but it looks like it is going to take a bit of experimenting (and time!) to get that working properly. All in all, a bit frustrating.

Roy Bøhmer

Wednesday 05 April 2006 2:16:17 pm

Hi!
This is some highly un-testet template code (with typos for free), that is supposed to loop through two arrays and sort them into a third array. As I said: I'm far from have tested it, but to make it work should require less time than making a custom fetch.



{let fetch1Array=fetch( 'content', 'list', hash(
       'parent_node_id', array(79,80,81,82,83,84,85,115), 
       'limit', 5, 
       'class_filter_type', 'include',
       'class_filter_array', array( 'class1' ),
       'sort_by', array( 'attribute', false(), 'class1/date_released' ) 
      ) ) 

   fetch2Array=fetch( 'content', 'list', hash(
      'parent_node_id', array(79,80,81,82,83,84,85,115), 
      'limit', 5, 
      'class_filter_type', 'include',
      'class_filter_array', array( 'class2' ),
      'sort_by', array( 'attribute', false(), 'class2/date_released' ) 
    ) ) 

   fetch1Count=sub( $fecth1Array|count, 1)
   fetch2Count=sub( $fecth2Array|count, 1)
   fetch1Iterator=0
   fetch2Iterator=0
   loop=true()
}

{let resultArray=array()}


{while $loop=true()}

   {if $fetch1Count|ge( $fetch1Iterator )}
      {if $fetch2Count|ge( $fetch2Iterator )}
          {if ge( $fetch1Array[$fetch1Iterator].data_map.date_released.content, $fetch2Array[$fetch2Iterator].data_map.date_released.content )}
             {set resultArray = $resultArray|append( $fetch1Array[$fetch1Iterator] ) }
             {set fetch1Iterator = sum( $fetch1Iterator, 1)}
          {else}
             {set resultArray = $resultArray|append( $fetch2Array[$fetch2Iterator] ) }
             {set fetch2Iterator = sum( $fetch2Iterator, 1)}
          {/if}

      {else}
          {set resultArray = $resultArray|merge( $fetch1Array|extract( sum( $fetch1Iterator, 1) ) )}
          {break}
      {/if}
           
   {else}
       {set resultArray = $resultArray|merge( $fetch2Array|extract( sum( $fetch2Iterator, 1) ) )}
       {break}
   {/if}


{/section}


{/let}

{* here you can use $resultArray *}

{/let}

lynn patchett

Friday 07 April 2006 12:53:08 am

Hi,

Thanks Roy, that is kind of you.

Another project has come up so I will need to return to this problem in a week or so. I will let you know how I get along with your code example, from what I see now it looks like a good simple solution.

I have also followed Kristof's suggestion and added this ability to the enhancement request list.

Thanks again
Lynn

Satoshi Kato

Saturday 23 September 2006 10:17:46 am

I solved this problem with ArraySortOperator by Marc Boon.
http://ez.no/community/contribs/template_plugins/arraysortoperator

I use two arrays.
One is a collection of fetched nodes. [(A) array]
Another is an associative array for sorting. [(B) array]

The key of (B) array is index of (A) array.
And value of (B) array is an attribute for sorting.

After sorting (B) array with asort or arsort operator,
I can get sorted indexes of (A) array with 'foreach' structure.

For example, if multiple classes have 'pub_date' attribute...

{let list_items=array() sort_attributes=array()}
{set $list_items=fetch_alias(children, hash(parent_node_id, $node.node_id))}
{section var=child loop=$list_items}
	{set $sort_attributes = $sort_attributes|merge(hash($child.index, $child.data_map.pub_date.content.timestamp))}
{/section}
{set $sort_attributes = $sort_attributes|arsort()}
{foreach $sort_attributes as $index => $item}
	{$list_items.$index.data_map.pub_date.content.timestamp|datetime('mydate')} 
	{$list_items.$index.name}<br />
{/foreach}
{/let}