Creating and Updating Nodes Programmatically in Drupal 7
The steps for programmatically creating a node are:
- Create a PHP object representing the node data
- Save the object using the node_save() function
While the mechanics are simple, there is an important responsibility involved. The Drupal work flow does data validation before calling the node_save() function; node_save() does no validation. By calling node_save() directly your code takes the responsibility for providing valid data.
Drupal 7 Changes
A quick note for those of you familiar with Drupal 6. You'll notice two changes in Drupal 7:
Body Field Is No Longer Special
In Drupal 6 the body field was special. Specifically, it had a different data structure than other fields and it always existed, even if it wasn't used. With Drupal 7 the body field is a standard field provided by core and is truly optional.
Language
Language specification is required for the node and some fields.
Filter Format
The format of the text field filter is now specified by machine name, not integer. For example: full_html, filtered_html, or plain_text. This is great news for moving contents between different Drupal systems.
Basic Node Creation
The following code assumes an unchanged Drupal 7 Standard installation and will create a Drupal 7 article node.
<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #FF8000">/**<br> * Basic Node Creation Example for Drupal 7<br> *<br> * This example:<br> * - Assumes a standard Drupal 7 installation<br> * - Does not verify that the field values are correct<br> */<br> </span><span style="color: #0000BB">$body_text </span><span style="color: #007700">= </span><span style="color: #DD0000">'This is the body text I want entered with the node.'</span><span style="color: #007700">;<br> <br> </span><span style="color: #0000BB">$node </span><span style="color: #007700">= new </span><span style="color: #0000BB">stdClass</span><span style="color: #007700">();<br> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">type </span><span style="color: #007700">= </span><span style="color: #DD0000">'article'</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">node_object_prepare</span><span style="color: #007700">(</span><span style="color: #0000BB">$node</span><span style="color: #007700">);<br> <br> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">title </span><span style="color: #007700">= </span><span style="color: #DD0000">'Node Created Programmatically on ' </span><span style="color: #007700">. </span><span style="color: #0000BB">date</span><span style="color: #007700">(</span><span style="color: #DD0000">'c'</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">language </span><span style="color: #007700">= </span><span style="color: #0000BB">LANGUAGE_NONE</span><span style="color: #007700">;<br><br> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">body</span><span style="color: #007700">[</span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">language</span><span style="color: #007700">][</span><span style="color: #0000BB">0</span><span style="color: #007700">][</span><span style="color: #DD0000">'value'</span><span style="color: #007700">] = </span><span style="color: #0000BB">$body_text</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">body</span><span style="color: #007700">[</span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">language</span><span style="color: #007700">][</span><span style="color: #0000BB">0</span><span style="color: #007700">][</span><span style="color: #DD0000">'summary'</span><span style="color: #007700">] = </span><span style="color: #0000BB">text_summary</span><span style="color: #007700">(</span><span style="color: #0000BB">$body_text</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">body</span><span style="color: #007700">[</span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">language</span><span style="color: #007700">][</span><span style="color: #0000BB">0</span><span style="color: #007700">][</span><span style="color: #DD0000">'format'</span><span style="color: #007700">] = </span><span style="color: #DD0000">'filtered_html'</span><span style="color: #007700">;<br> <br> </span><span style="color: #0000BB">$path </span><span style="color: #007700">= </span><span style="color: #DD0000">'content/programmatically_created_node_' </span><span style="color: #007700">. </span><span style="color: #0000BB">date</span><span style="color: #007700">(</span><span style="color: #DD0000">'YmdHis'</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">path </span><span style="color: #007700">= array(</span><span style="color: #DD0000">'alias' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$path</span><span style="color: #007700">);<br><br> </span><span style="color: #0000BB">node_save</span><span style="color: #007700">(</span><span style="color: #0000BB">$node</span><span style="color: #007700">);<br></span><span style="color: #0000BB">?></span></span>
Notes:
- The node_object_prepare() function does a number of useful things:
- Provides the default values for the status, promote, sticky, and revision flags. These values are type specific if $node->type is defined, and can be modified as required.Here is the data structure of $node after node_object_prepare() is called: stdClass Object
(
[type] => article
[status] => 1
[promote] => 1
[sticky] => 0
[uid] => 0
[created] => 1283285249
[revision] =>
[comment] => 2
[menu] => Array
(
[link_title] =>
[mlid] => 0
[plid] => 0
[menu_name] => main-menu:0
[weight] => 0
[options] => Array
(
)
[module] => menu
[expanded] => 0
[hidden] => 0
[has_children] => 0
[customized] => 0
[parent_depth_limit] => 8
)
) - Makes the current user the node owner by setting the $node->uid.(Note: If you are running from drush and haven't explicitly set a user, the node owner will be the anonymous user, typically UID 0.)
- Runs hook_prepare and hook_node_prepare on the object.
- Provides the default values for the status, promote, sticky, and revision flags. These values are type specific if $node->type is defined, and can be modified as required.Here is the data structure of $node after node_object_prepare() is called: stdClass Object
- The LANGUAGE_NONE string constant value is "und". It's useful to know this if you're ever looking at the node data values.
- The $node->body[$node->language][0]['format'] = 2 statement sets the Text format of the Body field to Filtered HTML. It is possible to set text format to a value the node owner isn't permitted to use, which will almost certainly cause undesirable consequences. Format values can be changed from the Administration menu, so be careful about what you assume.
- Node and Field API hooks called by node_save() may alter the saved data. For example, if the Pathauto module is enabled it will override the path given in this example.
- A list of Node and Field API hooks called during node_save() is available at the Drupal API Reference Site: Node API Hooks.
Updates
To update a node simply load it, make the changes, and then save it. The following example assumes there is a pre-existing node with the node id (nid) of 1.
<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #FF8000">/**<br> * Basic Node Update Example for Drupal 7<br> *<br> * This example:<br> * - Assumes a standard Drupal 7 installation<br> * - Assumes there is a node with a nid of 1<br> */<br> </span><span style="color: #0000BB">$nid </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$node </span><span style="color: #007700">= </span><span style="color: #0000BB">node_load</span><span style="color: #007700">(</span><span style="color: #0000BB">$nid</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">title </span><span style="color: #007700">= </span><span style="color: #DD0000">'Updated Title Text'</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">node_save</span><span style="color: #007700">(</span><span style="color: #0000BB">$node</span><span style="color: #007700">);<br></span><span style="color: #0000BB">?></span></span>
Remember, you are responsible for insuring the data being saved is valid.
Revisions
Revisions are a handy method for keeping a record of changes, programmatic or otherwise. If humans are involved in a review process they can also provide a measure of comfort and clarity by confirming what the program changed and what was preexisting, and providing the human reviewer a mechanism for undoing the change.
The following example assumes there is a pre-existing node with the node id (nid) of 1. The $node->log value isn't required but is useful.
<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #FF8000">/**<br> * Basic Node Revision Example for Drupal 7<br> *<br> * This example:<br> * - Assumes a standard Drupal 7 installation<br> * - Assumes there is a node with a nid of 1<br> */<br> </span><span style="color: #0000BB">$nid </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$node </span><span style="color: #007700">= </span><span style="color: #0000BB">node_load</span><span style="color: #007700">(</span><span style="color: #0000BB">$nid</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">body</span><span style="color: #007700">[</span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">language</span><span style="color: #007700">][</span><span style="color: #0000BB">0</span><span style="color: #007700">][</span><span style="color: #DD0000">'value'</span><span style="color: #007700">] .= </span><span style="color: #DD0000">"\nA line of text added by program."</span><span style="color: #007700">;<br><br> </span><span style="color: #FF8000">// Make this change a new revision<br> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">revision </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">log </span><span style="color: #007700">= </span><span style="color: #DD0000">'This node was programmatically updated at ' </span><span style="color: #007700">. </span><span style="color: #0000BB">date</span><span style="color: #007700">(</span><span style="color: #DD0000">'c'</span><span style="color: #007700">);<br> <br> </span><span style="color: #0000BB">node_save</span><span style="color: #007700">(</span><span style="color: #0000BB">$node</span><span style="color: #007700">);<br></span><span style="color: #0000BB">?></span></span>
After running the program the revision tab will display the update:
Understanding the Data Structures
There's no master directory of node data structures. The most reliable way to understand the data is checking the code. This may not be easy and I can not provide specific guidance. Here are some places I've found the information required to give me an understanding of a data structure.
- Trusted examples:
There are a number of well maintained modules that create Drupal content programmatically. Seeing how they deal with particular fields can be helpful. - Node Content Form Code:
The HTML forms used for adding and editing node content can provide understanding for how a field is properly used. In particular, the form validation. Because the code is generalized it is often difficult to home-in on the correct code unless you're familiar with Form API and how the code is called during a form submit. - Field API Documentation:
The Field API documentation is located at Drupal API Site: Field API. - Node and Field Hooks:
After determining the module responsible for saving the data check the code in applicable node and field hooks. - Module schema:
The data structure used in code is usually an analog of the structure used in the database. Drupal database tables are defined with schema that usually describes each database column. The schema definition can be seen using the Schema module or viewing the .install file of the applicable module.
Viewing Data Structures
The drush command line and/or the Devel module's Execute PHP code block can be used to display data structures. Here are sample commands for displaying a node object:
drush: drush php-eval "print print_r(node_load(12), 1)"
PHP block: dpr(node_load(12));
The "dpr" function uses the PHP print_r function to display the value. The Devel module has a number of other functions which use different display functions (e.g.: var_dump, krumo) and print to either the message area or display in the browser.
If you've discovered a research process, useful technique, or reference I haven't mentioned please be sure to add it to comments.
Note: This article was updated to reflect the final version of the API.
Tagged: