eZ Community » Forums » Developer » Multiple classes, common attribute fetch
expandshrink

Multiple classes, common attribute fetch

Multiple classes, common attribute fetch

Tuesday 05 May 2009 11:04:16 am - 17 replies

Hi,
I know this topic is repeated, but i havent found a solution.

Quoting from the fetch function list documentation:

"It is not possible to filter on attributes of different classes, for example it is not possible to filter on both "article/show_comments" and "folder/show_comments" in the same filter. "

Isnt there an good way to achieve this yet?. Im in a situation where i need to do a fetch from a php function to get objects from 2 different classes, like: "images, maps". those classes has a common "selection" attribute called: "category" .

I tried this:

$fetchParams = array( 
	 'ClassFilterType' => 'include', 
	 'ClassFilterArray' => array(30, 54) ,
	 'AttributeFilter' => array( 'or',
	        array(342, "=", 3),
		array(531, "=", 3 )
	 ) );

  $result = eZContentObjectTreeNode::subTreeCountByNodeID( $fetchParams, 221 );

The fetch returns in no results, but works fine by removing the statement.

array(531, "=", 3 )

Thank you.

Modified on Tuesday 05 May 2009 11:15:45 am by Luis Micunco

Tuesday 05 May 2009 11:22:16 am

Hello,

You can do this only using custom extended attribute filter. I will try to find an example and post it here

Tuesday 05 May 2009 11:38:35 am

Found something for ez3 (php4). If you working with ez4 (php5) you will need to modify the constructor call.
This filter is used for objectrelation attribute, but you can make it to work with selection attribute.

Make a new extension with file kernel\classes\ezcategoryfilter.php

<?php

class eZExtendedCategoryFilter
{
    /*!      Constructor     */
    function eZExtendedCategoryFilter()
    {
    }

    function createSqlParts( $params )
    {
        $result = array( 'tables' => '', 'joins'  => '' );

        if ( isset( $params['classes'] ) )
        {
             $classes = $params['classes'];
        } else
		return;

        $filterSQL = array();
        $filterSQL['from']  = ", ezcontentobject_link i1 ";

	$attribute_ids = array();
	foreach ($classes as $class) {
			array_push($attribute_ids,eZContentObjectTreeNode::classAttributeIDByIdentifier( $class . '/category' ));
	}
	$class_cond = array();
	foreach ($attribute_ids as $aid) {
		if ($aid) {
		array_push($class_cond, 'i1.contentclassattribute_id = '.$aid);
		}
	}

        $string_class_cond = implode(" OR ",$class_cond);

        $filterSQL['where'] = " ( i1.from_contentobject_id = ezcontentobject.id AND (" . $string_class_cond . ") AND 			   i1.from_contentobject_version = ezcontentobject.current_version AND i1.to_contentobject_id = " . $params['object_id'] . ") AND ";

	return array( 'tables' => $filterSQL['from'], 'joins'  => $filterSQL['where'] );

    }
}

?>

Also add this to extendedattributefilter.ini:

[ExtendedCategoryFilter]
#The name of the extension where the filtering code is defined.
ExtensionName=your_extension

#The name of the filter class.
ClassName=eZExtendedCategoryFilter

#The name of the method which is called to generate the SQL parts.
MethodName=createSqlParts

#The file which should be included (extension/myextension will automatically be prepended).
FileName=kernel/classes/ezcategoryfilter.php

And activate the extension.
You then use this in your templates like this:

fetch( 'content', 'tree', hash( parent_node_id, $parent_node_id ,
'extended_attribute_filter', hash('id','ExtendedCategoryFilter','params',hash('object_id', $value,'classes',array('class1','class2'))),	))}

Tuesday 05 May 2009 12:22:06 pm

Hi.
I will give it a try.

Thanks a lot.

Friday 08 May 2009 10:39:11 am

Hi.
Now i got it to work.
But what about the "sort by". I need also to "sort" the result by a "date" attribute. Again its is a common attribute in both classes with the same identifier.

Is it possible to include an "ORDER BY" o something similiar in the code ?.
Thank you. I will post my result code later.

Friday 08 May 2009 10:56:09 am

In extended attribute filter you are attaching some SQL parts to ez query so you probably can add your 'order by'

Friday 08 May 2009 11:01:08 am

Yes.
I think there is a default "ORDER BY" value.
Looking at the MYSQL DEBUG of my fetch, it appends:

"ORDER BY path_string ASC"

Any idea? Thank you

Modified on Friday 08 May 2009 11:02:53 am by Luis Micunco

Friday 08 May 2009 12:37:58 pm

Hm, just checked some code, and it seems it can't be done.
createSqlParts function returns 'tables' and 'joins' and that's it.

There is no extended sorting sad.gif Emoticon

Monday 11 May 2009 10:37:16 am

Actually you can return columns as well. The docs don't say it but you can have a colums part for the return array, then you can have the ORDER BY to order by that custom column as well.

Check this for clarification http://pubsvn.ez.no/doxygen/4.0/h...jecttreenode_8php-source.html#l00870

Monday 11 May 2009 12:16:39 pm

You mean like sending with columns variable additional attribute with AS FOOBAR, and then in fetch sort it with 'FOOBAR'?

Hm, could work, but I don't have time to experiment :/

Wednesday 13 May 2009 12:53:48 am

Yup exactly happy.gif Emoticon

Wednesday 13 May 2009 7:19:11 pm

Hi there again.
This worked for the sorting:

fetch( 'content', 'tree', hash( parent_node_id, $parent_node_id ,
'sort_by', array(array('i1.sort_key_int', 0)),
'extended_attribute_filter', hash('id','ExtendedCategoryFilter','params',hash('object_id', $value,'classes',array('class1','class2'))), ))}

I think this is because "i1" is the "ezcontentobject_attribute" alias, and "sort_key_int" the "ezcontentobject_attribute" field im sorting by.
I will post the entire code then-
Thanks to all

Modified on Wednesday 13 May 2009 7:20:38 pm by Luis Micunco

Saturday 23 May 2009 12:44:57 pm

Hey Luis,

I just stumble upon the very same problem as you, and it seems that you found your way through. Could you share your solution ?

Thanks in advance !

Benjamin

Wednesday 29 July 2009 3:25:20 pm

Benjamin, and others,

Maybe I'm too late, but here's my extende PHP filter. First off, important to know is that I have multiple classes that share a category string. A dropdown box in my case is used to filter through these categories, hence the 'LIKE' statement (categories can be added just by typing text and separating by comma's).

Here's my code (based on previous steps discussed in this thread):

<?php    
class eZExtendedCategoryFilter
{    
	/*!     Constructor    */    
	function eZExtendedCategoryFilter()
	{     
	}       
	 
	function createSqlParts( $params )     
	{         
		$result = array( 'tables' => '', 'joins' => '' );           
		if ( isset( $params['classes'] ) )        
		{              
			$classes = $params['classes'];         
		} 
		else                  
		  return; 
	  
	  	$filterSQL = array();         
	  	$filterSQL['from'] = ", ezcontentobject_attribute ";            
	  	$attribute_ids = array();          
  
		foreach ($classes as $class) {                          
			array_push($attribute_ids,eZContentObjectTreeNode::classAttributeIDByIdentifier( $class . '/categories' ));          
		}          
		
		$class_cond = array();          
		foreach ($attribute_ids as $aid)
		{                  
			if ($aid)
			{                  
				array_push($class_cond, 'ezcontentobject_attribute.contentclassattribute_id = '.$aid);                  
			}          
		}           
		
		$string_class_cond = implode(" OR ",$class_cond);
		$filterSQL['where'] = " ( ezcontentobject_attribute.contentobject_id = ezcontentobject.id AND (" . 
								$string_class_cond . 
								") AND ezcontentobject_attribute.version = ezcontentobject.current_version "
								." AND ezcontentobject_attribute.data_text LIKE '%" . 
								$params['textLIKEfilter'] . 
								"%') AND ";   
		
		return array( 'tables' => $filterSQL['from'], 'joins' => $filterSQL['where'] );       
	}  
}    
?>

And the template function looks like this:

{def $list=fetch('content','list',hash('parent_node_id',$myNodeID, 
												offset, $#view_parameters.offset, 
												sort_by, array( 'priority', false()), 
												limit, 5,	
												'extended_attribute_filter', hash('id','ExtendedCategoryFilter',
																				'params',
																					hash(	'textLIKEfilter', ezhttp('categories', 'get'),
																							'classes',array('class1','class2')
																				)
																			)									
												))}

Hopefully this helps you, and others.

Modified on Wednesday 29 July 2009 3:26:57 pm by Clemens T

Wednesday 29 July 2009 3:42:21 pm

Hey Clemens, thanks for you filter, which seems to open an interesting way to filter on multiple classes. I should use it one way or another next time I stumble upon the same problem.

Oh, and by the way, you shouldn't use ezhttp operator in your template if it's a view template, use View Parameters instead blunk.gif Emoticon

Friday 21 January 2011 12:22:00 pm

Hi

I was only interested by sorting on different attributes in differents classes within a fetch

Base on previous posts, I was able to correct the code ( EZ v 4.x) in this purpose :

<?php
 
class eZExtendedCategoryFilter
{
    /*!      Constructor     */
    function eZExtendedCategoryFilter()
    {
    }
 
    function createSqlParts( $params )
    {
        $result = array( 'tables' => '', 'joins'  => '' );
 
        if ( isset( $params['classes'] ) )
        {
             $classes = $params['classes'];
        } else
        return;
 
        if ( isset( $params['sort_fields'] ) )
        {
             $sort_fields = $params['sort_fields'];
        } else
        return;
 
        $filterSQL = array();
        $filterSQL['from']  = ", ezcontentobject_attribute  ";
 
    $attribute_ids = array();
    $i=0;
    foreach ($classes as $class) {
            array_push($attribute_ids,eZContentObjectTreeNode::classAttributeIDByIdentifier( $class . '/'.$sort_fields[$i] ));
            $i++;
    }
    $class_cond = array();
    foreach ($attribute_ids as $aid) {
        if ($aid) {
        array_push($class_cond, 'ezcontentobject_attribute.contentclassattribute_id = '.$aid);
        }
    }
 
        $string_class_cond = implode(" OR ",$class_cond);
 
        $filterSQL['where'] = " ( ezcontentobject_attribute.contentobject_id = ezcontentobject.id AND (" . $string_class_cond . "blunk.gif Emoticon AND                ezcontentobject_attribute.version = ezcontentobject.current_version ". "blunk.gif Emoticon AND ";
 
    return array( 'tables' => $filterSQL['from'], 'joins'  => $filterSQL['where'] );
 
    }
}
 
?>

Template call

{def $news=fetch( 'content', 'tree', hash( parent_node_id, $parent_node_id ,
'limit',$nbnews,
'sort_by', array(array('ezcontentobject_attribute.data_int', 0)),
'extended_attribute_filter', hash('id','ExtendedCategoryFilter','params',hash('classes',array('press','article_mainpage'),'sort_fields',array('date','publish_date')))
))
  • sort_by : put the data type of the attributes. i.e my attributes were date. they are store as data_int en EZ
  • params :
    classes : put the class names ,
    sort_fields: put the user defined identifiers on which the sort should run, in the same order as class names.
    i.e . I have two classes ( press - field identifier : date / article_mainpage - field identifier : publish_date )

Thanks everyone for helping me to write this "missing" feature

Sunday 23 January 2011 10:10:19 pm

And also, you could use eZ Find :

{def $search=fetch( ezfind, search,
     hash( query , '',
           'class_id', array('press','article_mainpage'),
           'limit', 10,
           'sort_by', hash('attr_date_dt', 'desc')
))}

Modified on Sunday 23 January 2011 10:12:38 pm by gilles guirand

Monday 13 August 2012 10:48:15 am

Quote from Clemens T :

Hopefully this helps you, and others.

I've got this working, but now need to incorporate other languages - this version seems to apply to just the main language.  Any ideas on how to incorporate 

ezcontentobject.language_mask
ezcontentobject.language_id
ezcontentobject.language_code

to get the correct behaviour? 

Update #2: this is indeed still a problem

Modified on Monday 13 August 2012 12:13:57 pm by Geoff Bentley

expandshrink

You must be logged in to post messages in this topic!

36 542 Users on board!

Forums menu