
Fetching eZ publish content objects with PHP
One of the most often used eZ publish functions is ?fetch?. There are a lot of examples in the new and old documentation that show how to fetch content in the eZ publish templates, but many users ask how to fetch eZ publish content objects using PHP.
NOTE: In eZ Publish 4.0 (PHP 5 based) and higher static class functions are now marked as static. One of the more important change is that eZContentObjectTreeNode::subTree() is no longer static. Because it is no longer marked as static, you can not call it as a static function any more. Instead, use eZContentObjectTreeNode::subTreeByNodeID() to fetch data. Note created: 2007/12/13
This tutorial shows some common examples of fetching content with PHP. Using simple CLI scripts, you can practice content fetching with PHP without changing eZ publish. These examples can be used in your custom modules as well. First we need to create a simple CLI script for testing. We could use the eZ publish ?custom? module, but with a CLI script we don't need to define extensions, settings, etc. In other words it will be faster.
Create a new file called ?fetchcontent.php? under the eZ publish root directory and put in the following code:
#!/usr/bin/env php <?php include_once( 'lib/ezutils/classes/ezcli.php' ); include_once( 'kernel/classes/ezscript.php' ); $cli =& eZCLI::instance(); $script =& eZScript::instance(); $script->startup(); $options = $script->getOptions(); $script->initialize(); $script->shutdown(); ?>
Now we have defined a CLI script that is ready to use. This script does nothing, of course. You can test it by executing it from the eZ publish root directory with the following command:
$ php fetchcontent.php -d
NOTE: On Windows, make sure you use the correct php.exe file. The PHP CLI is usually installed at PHP_DIR\cli\php.exe. The CLI script must be executed from the eZ publish root directory.
-d option is used for debugging. The debug output will be displayed below the results.
-dall option will print all debug messages.
To use the code examples shown below, put a line after $script->initialize(); and before line $script->shutdown();
[...] $script->initialize(); include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); // {def $node=fetch( 'content', 'node', hash( 'node_id', 2 ) )} $node =& eZContentObjectTreeNode::fetch( 2 ); // {$node.name} $cli->output($node->attribute( 'name' ) ); $script->shutdown(); [...]
In the PHP comments you will find template code examples that do the same thing as the PHP code.
list/tree fetch examples
Example 1
include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); // {def $nodes=fetch( 'content', 'list', hash( 'parent_node_id', 2 ) )} $nodes =& eZContentObjectTreeNode::subTree( array( 'Depth' => 1 ), 2 ); // {foreach $nodes as $node} // {$node.name}<br /> // {/foreach} foreach ( $nodes as $node ) { $cli->output($node->attribute( 'name' ) ); }
This example outputs the names of all nodes that are below node number 2.
Example 2
include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); // {def $nodes=fetch( 'content', 'list', hash( 'parent_node_id', 2, 'sort_by', array( 'published', false() ) ) )} $nodes =& eZContentObjectTreeNode::subTree( array( 'Depth' => 1, 'SortBy' => array( 'published', false ) ), 2 ); // {foreach $nodes as $node} // {$node.name}<br /> // {/foreach} foreach ( $nodes as $node ) { $cli->output( $node->attribute( 'name' ) ); }
This example demonstrates how to fetch all nodes that are children of node number 2. The nodes are sorted according to the time they were published; the most recently published node will be the first element in the collection.
Example 3
include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); // {def $nodes=fetch( 'content', 'list', hash( 'parent_node_id', 2, 'class _filter _type', include, 'class_filter_array', array( 'folder' ) ) )} $nodes =& eZContentObjectTreeNode::subTree( array( 'Depth' => 1, 'ClassFilterType' => 'include', 'ClassFilterArray' => array( 'folder' ) ), 2 ); // {foreach $nodes as $node} // {$node.name}<br /> // {/foreach} foreach ( $nodes as $node ) { $cli->output( $node->attribute( 'name' ) ); }
This example demonstrates how to use class filtering to fetch only nodes that reference objects that are instances of the class ?folder?.
Example 4
include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); // {def $node=fetch( 'content', 'node', hash( 'node_id', 2 ) )} $node =& eZContentObjectTreeNode::fetch( 2 ); // {$node.name} $cli->output( $node->attribute( 'name' ) );
Fetches node number 2 and outputs the name of the object that is encapsulated by that node.
Example 5
include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); {def $node=fetch( 'content', 'node', hash( 'node_path', 'weblog/another_blog' ) )} $node =& eZContentObjectTreeNode::fetchByURLPath( 'weblog/another_blog' ); // {$node.name} $cli->output( $node->attribute( 'name' ) );
Fetches the node by the specified path and outputs the name of the object that is encapsulated by that node.
The difference between parameters from the template list/tree function and PHP is the naming convention. In templates we use 'class_filter_type', while in PHP we use ClassFilterType (written without underscores and starting every word with a capital letter). Check eZContentObjectTreeNode::subTree() for a list of the available parameters.
Miscellaneous
Search
include_once( "kernel/classes/ezsearch.php" ); // {def $search=fetch( 'content', 'search', hash( 'text', 'Weblog', 'section_id', 1 ) )} $search = eZSearch::search( 'Weblog', array( 'SearchSectionID' => 1 ) ); $cli->output( "The search returned " . $search['SearchCount'] . " matches." ); // {foreach $search.SearchResult as $matched_node} // {$matched_node.name} <br /> // {/foreach} foreach ( $search['SearchResult'] as $matchedNode ) { $cli->output( $matchedNode->attribute( 'name' ) ); }
Outputs the names of all nodes that encapsulate objects of section 1 containing the word "Weblog".
User data
include_once( 'kernel/classes/datatypes/ezuser/ezuser.php' ); // {def $user=fetch( 'user', 'current_user' )} $user = eZUser::currentuser(); // {$user.login} {$user.email} $cli->output( "Login: ". $user->attribute( 'login' ) . "\nE-mail: " . $user->attribute( 'email' ) );
Fetches the user by the specified ID and outputs the Login and E-mail of the user object. Use eZUser::fetch( user_id ) if you want fetch the user object by ID.
Content object attributes data
include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); // {def $node=fetch( 'content', 'node', hash( 'node_id', 2 ) )} $node =& eZContentObjectTreeNode::fetch( 2 ); // {$node.object.data_map} $object =& $node->object(); $dataMap =& $object->dataMap(); // {$node.object.data_map.name.data_text} $name = $dataMap['name']->attribute('data_text'); // {$node.object.data_map.short_name.data_text} $shortName = $dataMap['short_name']->attribute('data_text'); // {$node.object.data_map.description.content.output.output_text} $shortDescription =& $dataMap['short_description']->content(); $shortDescriptionOutput =& $shortDescription->attribute('output'); $shortDescriptionOutputText = $shortDescriptionOutput->attribute('output_text'); // {$node.object.data_map.description.content.output.output_text} $description =& $dataMap['description']->content(); $descriptionOutput =& $description->attribute('output'); $descriptionOutputText = $descriptionOutput->attribute('output_text'); // Print output $cli->output( "Name:\n" . $name ); $cli->output( "Short name:\n" . $shortName ); $cli->output( "Short description:\n" . $shortDescriptionOutputText ); $cli->output( "Description:\n" . $descriptionOutputText );
Fetches node number 2 and outputs the content of the object attributes that is encapsulated by that node.
Collection of classes
include_once( 'kernel/classes/ezcontentclass.php' ); // {def $classes=fetch( 'class', 'list' )} $classes = eZContentClass::fetchList( 0, true, false, null, null, false ); // {foreach $classes as $class} // {$class.name} <br /> // {/foreach} foreach ($classes as $class) { $cli->output( $class->attribute( 'name' ) ); }
Outputs the names of all classes.
include_once( 'kernel/classes/ezcontentclass.php' ); // {def $classes=fetch( 'class', 'list', hash( 'class_filter', array( 1, 2, 3 ) ) )} $classes = eZContentClass::fetchList( 0, true, false, null, null, array( 1, 2, 3 ) ); // {foreach $classes as $class} // {$class.name} <br /> // {/foreach} foreach ($classes as $class) { $cli->output( $class->attribute( 'name' ) ); }
Outputs the names of classes numbered 1, 2 and 3.
Display image full path
include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); // {def $node=fetch( 'content', 'node', hash( 'node_id', 82 ) )} $node =& eZContentObjectTreeNode::fetch( 82 ); // {$node.object.data_map} $object =& $node->object(); $dataMap =& $object->dataMap(); // {$node.object.data_map.image.content[original].full_path} $image =& $dataMap['image']->content(); $aliasList =& $image->aliasList(); $fullPath = $aliasList['original']['full_path']; $cli->output( $fullPath );
Fetches node number 82 (with the image datatype attribute) and outputs the image's full path of the object that is encapsulated by that node.
Remove content object
include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); $node =& eZContentObjectTreeNode::fetch( 192 ); $object =& $node->object(); $object->remove(); $object->purge();
Fetches node number 192 and removes the object that is encapsulated by that node from the database. Use only $object->remove(); if you just want to move the object to the trash.
Remove group of nodes
include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); include_once( 'kernel/classes/datatypes/ezuser/ezuser.php' ); // Set admin user as currently logged in. $user =& eZUser::fetchByName( 'admin' ); eZUser::setCurrentlyLoggedInUser( $user, $user->attribute('contentobject_id') ); $deleteIDArray = array(); $nodes =& eZContentObjectTreeNode::subTree( array( 'Depth' => 1 ), 102 ); foreach ( $nodes as $node ) { $deleteIDArray[] = $node->attribute( 'main_node_id' ); } eZContentObjectTreeNode::removeSubtrees( $deleteIDArray, false );
Removes all nodes that are below node number 102.
NOTE: eZContentObjectTreeNode::removeSubtrees checks the permissions of the current user. That is why we need to switch to a user who has ?remove? rights (?admin? in our example).
These examples can be re-used in your custom modules, template operators, etc. Happy fetching!

Comments

adding 'autoload.php';
When tried this script, it resulted errors about couldn't find some objects.
After comparing to runcronjobs.php on eZ Publish 4, then found that we need to add a statement:
require 'autoload.php'; in the beginning of the script.
Thanks for such a very useful tutorial.

eZ Publish 4 and higher
In eZ Publish 4.0 (PHP 5 based) and higher static class functions are now marked as static. One of the more important change is that eZContentObjectTreeNode::subTree() is no longer static. Because it is no longer marked as static, you can not call it as a static function any more. Instead, use eZContentObjectTreeNode::subTreeByNodeID() to fetch data.

what about tree?
I've tried to use the subtree function with a depth parameter > 1, and had the impression it was not workin ... did I miss something, like the DepthOperator for instance ?
Regards,
N.

Note
If you want to test fetch with eZFunctionHandler::execute and CLI script make sure that script uses modules. Replace line:
$script =& eZScript::instance();
with:
$script =& eZScript::instance( array( 'use-modules' => true ) );

Great ...
Great resource to unsterstand kernel ... Merci !

Thanks!
Hi All,
Thanks for comments. I think we can publish enhanced version of this tutorial on ez.no. It requires some more explanations in some cases. Also should include information about eZFunctionHandler::execute(). Thanks Kristian!
It should be publish on ez.no before conference. If know any cool examples let me know about them, we can include it as well. Of course I will remember about credits ;)
Cheers,
Łukasz

Nice tutorial!
And a very useful comment on something unknown to me until now: eZFunctionHandler::execute
Regards
Paul

Great
Great tutorial for kernel newbies!

The same way as in templates
Hi,
This could be nice as an tutorial on ez.no.
If you are willing to sacrifice a tiny bit of speed, i would recommend do it the same way as is done in the templates. That is handled by eZFunctionHandler::execute in the following way:
$nodes = eZFunctionHandler::execute('content','tree', array('parent_node_id' => $top_node_id,
'class_filter_type' => 'include',
'class_filter_array' => array( 'article' ) ) );
The syntax here is exactly the same as in the templates (except you don't use 'hash' to create associative arrays, but rather PHP's array function.
Happy hacking!






Thank you Luke
Monday 06 July 2009 3:51:06 pm
R K
..and I think it's a very good idea to show PHP style and eZ template syntax along each other, Makes understanding it a lot easier.
This is the second version of the comment.