One quarter English
One quarter English

Creating nodes in PHP with eZ Publish

April 11th, 2010

There are many threads which detail creating objects in PHP but they all seem to do things slightly differently. Many of the posts are very old and out of date and so they use a very convoluted way of creating objects (this is just half of it!). Since eZ Publish 3.9 there’s been a much better approach to take but it is very well hidden in forum posts. Here’s a summary of how you can use it.

Who is importing the data?

First things first. Before importing any data you need to work out who should be? If you are using a template which is calling this functionality then you can pull in the current user. If you are running the script from the command line, you may want to use a specific user.

Current User

Pulling in the current user is easy enough, using the static method currentUser() from within eZUser you pull out the user currently logged in. If nobody is logged in, the anonymous account within the CMS is used (typically if you run the function in a custom PHP Script you will be returned the anonymous user. I would recommend using this approach if the import has been triggered by an action from the user on the site.

$user = eZUser::currentUser();

A specific user

You will typically want to do this if you are running a PHP script and I would recommend creating an import user for the task. You can pull out a specific user by name or email. Alternatively you can statically use an ID for the creation process but you may find these vary across your dev and live environments so I wouldn’t recommend it.

For name:

$user = eZUser::fetchByName( ‘admin’ );
if (!$user){//if no user exists let’s pull out the current user:
        $user = eZUser::currentUser();
}

or for email…

$user = eZUser::fetchByEmail( ‘admin@admin.com’ );
if (!$user){//again, default to current if necessary
        $user = eZUser::currentUser();
}

Adding the Content

In this example I’m just creating a folder within a folder in the content root called “my articles folder”. By making sure you are not using any hard coded IDs as I have done below, you are ensuring that they will be no discrepancies in the script when you run it on your staging and live environments:

//getting information required to setup the node:
$user = eZUser::fetchByName( ‘import_user’ );
if (!$user){//if no user exists let’s pull out the current user:
$user = eZUser::currentUser();
}
$parent_node = eZContentObjectTreeNode::fetchByURLPath(‘my_articles_folder’);//note the underscores in place of hyphens.
//The parent node is always 2 so skip this line if you need to place objects in the home folder and replace the reference to this variable below
//we will use the parent node to tell eZ Publish where we want our node to be stored.

//setting node details
$params = array();
$params ['class_identifier'] = ‘folder’; //class name (found within setup=>classes in admin if you need it
$params['creator_id'] = $user->ContentObjectID;//using the user created above
$params['parent_node_id']=$parent_node->NodeID;//pulling the node id out of the parent, replace this with 2 if the content needs to go in the home folder
$params['section_id'] = $parent_node->ContentObject->SectionID;//we don’t need to do this as the section will default to that of the parent but if you want to use a different node the same approach can be used.

//setting attribute values
$attributesData = array ( ) ;
$attributesData['name'] = ‘Testing…’ ;
$attributesData ['short_name'] = ‘test’ ;

$params['attributes'] = $attributesData;

$contentObject = eZContentFunctions::createAndPublishObject($params);

And that is it! The basic script is simple enough but there are a few caveats you need to be aware of. Images, files, XML and related object fields can all be added using this approach but they are slightly more complicated to import:

Importing XML fields

XML fields are more difficult due to the structure they are stored in in the database. You need to make sure you wrap your text within the extra xml layers to add it successfully. eZ Publish has some built in methods for doing this so we can just use these. :

//updating the structure for the valid XML
    $XMLContent = "<p>David’s Test String</p>";//my example content
   //creating and setting up the parser
   $parser = new eZSimplifiedXMLInputParser( );
    $parser->setParseLineBreaks( true );
    //parsing the content
    $document = $parser->process( $XMLContent );
   
   //adding the content to an object
    $attributesData [‘description’] = eZXMLTextType::domString( $document );

Importing images and files

Images and files are added by using in the name of your file so they quite straightforward. The only addition is that you need to make sure to specify the storage directory for the file so that eZ knows where to look. If you have issues with a missing image then the problem is most likely going to be there (if you are running the script through the command line use the information found here to view the debug information). The following code is based on the previous example:

//getting information required to setup the node:
$user = eZUser::fetchByName( ‘import_user’ );
if (!$user){
        $user = eZUser::currentUser();
}
$parent_node = eZContentObjectTreeNode::fetchByURLPath(‘Media/Images’);

//setting node details
$params = array();
$params [‘class_identifier’] = ‘image’;
$params[‘creator_id’] = $user->ContentObjectID;//using the user created above
$params[‘parent_node_id’]=$parent_node->NodeID;//pulling the node id out of the parent
$params[’section_id’] = $parent_node->ContentObject->SectionID; //we can also pull the section out of the parent
$params [’storage_dir’ ] = $_SERVER[‘PWD’].‘/var/ezflow_site/storage/import_images/’;/*required so ez knows where to look.
The ending "/" required. $_SERVER['pwd'] is being used as the script is being run through the command line*/

//setting attribute values
$attributesData = array ( ) ;
$attributesData[‘name’] = ‘Adding a random image’ ;
$attributesData [ ‘image’ ] = ‘my_image’ ;

//storing xml content for the caption
$XMLContent = "<p>David’s Picture Test</p>";
$parser = new eZSimplifiedXMLInputParser( );
$parser->setParseLineBreaks( true );
$document = $parser->process( $XMLContent );
$xmlString = eZXMLTextType::domString( $document );
$attributesData [‘caption’] = $xmlString;

$params[‘attributes’] = $attributesData;

//publishing node
$contentObject = eZContentFunctions::createAndPublishObject($params);

Adding Related Objects to specific attributes

Various types in eZ Publish uses a related object so that you can specify a file which can be attached to an article To do this you just need to supply the object ID you just created as the attribute (see the code below).

//after the previous example store the object ID of the image:
$image_id = $contentObject->ID;

//then, when you specify the attributes of the image gallery use the ID:
$attributesData [‘image’] = $image_id;

For some types this approach will not work. For instance, Image Galleries have a field for a related object. The problem is that more than likely this will need to be an image which sits below the gallery itself. The solution for this is to use the static method updateAndPublishObject in the eZContentFunctions class (this is very comparable to the createAndPublishObject method used in this post). This allows you to add the related object after you have published the gallery and it’s images.

Adding Other Related Objects

Since every node in eZ Publish can also have other related objects this is also a key thing you may have to do. It is strictly not possible with the createAndPublishObject function we are using but the function returns the content object that has been created. Due to this we can attach the related objects directly to this. The code below assumes we are pulling out the image id as we were previously:

$image_id = $contentObject->ID;//first we need the object id, let’s pull out the image ID as we did before
$contentObject->appendInputRelationList(array($image_id),eZContentObject::RELATION_COMMON);
//create the relation
$contentObject->commitInputRelations($contentObject->CurrentVersion);//commit to store it in the database

Tags: ,

Leave a Reply

(will not be published)