Lesson 4.3: Reading and writing content from PHP
Imports, migrations and scheduled jobs read and write content from PHP. The kernel has a small, safe API for it: fetch an object or node, read its attributes by identifier, and create or update an object through the same publish operation the edit form uses. In this lesson learners write a script that reads a note, creates a new one and updates it.
Note
This script writes content. Run it only on the training installation.
At a glance
| Course | Developers |
| Module | Module 4: Content classes and datatypes |
| Duration | 55 minutes (15 presenting, 40 exercise) |
| Level | Intermediate |
| Audience | Developers |
| Prerequisites | Lesson 4.1: the Note class |
Learning objectives
After this lesson, learners can:
- fetch a node with
eZContentObjectTreeNode::fetch()and its object withobject(); - read attributes by identifier with
dataMap()andtoString(); - create and publish an object with
eZContentFunctions::createAndPublishObject(); - update an object with
eZContentFunctions::updateAndPublishObject(); - use a
remote_idso a script can find its own objects again.
Trainer's notes
How to present it
Source: the documentation comments of kernel/classes/ezcontentfunctions.php.
- Reading (3 minutes). A node gives its object with
$node->object();$object->dataMap()returns the attributes by identifier, likedata_mapin a template.toString()returns a datatype's value as a string. createAndPublishObject(5 minutes). Its parameters areparent_node_id,class_identifier,creator_id,attributes(identifier to value), and optionallyremote_id,section_idandstorage_dir. Values are strings in the format of each datatype'sfromString(); read that method when in doubt. It returns the object orfalse.updateAndPublishObject(3 minutes). Takes an object andattributes(and optionallylanguage), makes a new version and publishes it. A missing or empty attribute list is refused before anything changes.- Notifications (2 minutes). Both methods take a last argument
$notify;falsepublishes without notification events, like "Publish without notification" in the edit form. remote_id(2 minutes). A unique string you choose.eZContentObject::fetchByRemoteID()finds the object again, so an import can update instead of duplicating.
Common questions
Which user publishes? The creator_id you give (the content object ID of a user), otherwise the current user.
In a script the current user is anonymous; give an editor's or administrator's ID.
How do I write rich text? As the XML the rich text datatype stores; the example in the comment of
updateAndPublishObject() shows a <section> with <paragraph>. Plain text attributes (ezstring, eztext)
take plain strings.
Are permissions checked? The API publishes what you give it; the script is trusted code. Check permissions yourself when a script acts for a user.
Pitfalls
- Running the script twice. Without a
remote_idcheck, the second run creates a second object. Fetch by remote ID first. - Wrong parent.
parent_node_idis a node ID, not an object ID. - Huge loops. Thousands of objects in one run need memory care (clearing the in-memory object cache between batches) and are better done as content jobs or in batches; start small.
Hands-on exercise
On the training installation, with the Note class and your course folder. <folder node ID> is the node ID of
your course folder (shown in the administration).
Create
extension/mysite_hello/scripts/notes.php:// Create or update a note: php bin/php/ezexec.php extension/mysite_hello/scripts/notes.php $cli = eZCLI::instance(); $parentNodeID = 0; // the node ID of your course folder $remoteID = 'mysite_hello_note_1'; $admin = eZUser::fetchByName( 'admin' ); $creatorID = $admin instanceof eZUser ? $admin->attribute( 'contentobject_id' ) : false; $object = eZContentObject::fetchByRemoteID( $remoteID ); if ( !$object instanceof eZContentObject ) { $object = eZContentFunctions::createAndPublishObject( array( 'parent_node_id' => $parentNodeID, 'class_identifier' => 'note', 'creator_id' => $creatorID, 'remote_id' => $remoteID, 'attributes' => array( 'title' => 'Created by a script', 'body' => 'First version.' ) ) ); $cli->output( $object ? 'Created object ' . $object->attribute( 'id' ) : 'Create failed' ); } else { $ok = eZContentFunctions::updateAndPublishObject( $object, array( 'attributes' => array( 'body' => 'Updated at ' . date( 'H:i:s' ) ) ) ); $cli->output( $ok ? 'Updated object ' . $object->attribute( 'id' ) : 'Update failed' ); } $object = eZContentObject::fetchByRemoteID( $remoteID ); if ( $object instanceof eZContentObject ) { $dataMap = $object->dataMap(); $cli->output( 'Title: ' . $dataMap['title']->toString() ); $cli->output( 'Body: ' . $dataMap['body']->toString() ); $cli->output( 'Version: ' . $object->attribute( 'current_version' ) ); }Set
$parentNodeIDto your course folder's node ID.Check it with
php -l, then run it:php bin/php/ezexec.php extension/mysite_hello/scripts/notes.php.Find the new note in your course folder in the administration.
Run the script again.
Open the note's Manage versions page (or its version list) and count the versions.
Open the note's page in the administration and check Owner or the version list: the creator is the administrator, not the anonymous user.
Commit the script.
Expected result
- Step 3 prints
Created object <ID>, the title,First version.andVersion: 1. - Step 5 prints
Updated object <ID>, the new body andVersion: 2. - Step 6: the note has two versions.
- The trainer checks one learner's note in the administration.
Quiz
- Which method returns an object's attributes by identifier?
- Which parameter lets a script find its own object again?
A.
section_idB.remote_idC.storage_dirD.creator_id - What does
createAndPublishObjectreturn when it fails? - What happens when
updateAndPublishObjectis called with an empty attribute list? - Is
parent_node_ida node ID or an object ID?
Answers
$object->dataMap().- B.
remote_id, found witheZContentObject::fetchByRemoteID(). false.- It is refused before anything changes.
- A node ID.
Further reading
- The content model and editing content: versions and drafts.
- Content jobs: large operations in batches.
- Publish without notification: the
$notifyargument.
Related pages
- Module 4: Content classes and datatypes
- Developers: course overview
- Trainers: start here
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.