Drupal 6 - Inserting & Updating Nodes Programmatically

On a number of occasions in the last year, we've created new websites that required importing a great deal of content from an old website. Instead of going through the hassle (not to mention the sheer length of time) of entering each page via the node insert form, it's much easier to utilize the programmatic node insert feature of Drupal.

Per the sources at the end of this article and our own investigations, we've identified a number of obstacles that can come into play when trying to import nodes programmatically, and it's our intent to help clear up as many of those obstacles as possible to make it easy for you to import your content into nodes in Drupal. This article assumes that you've got the content ready for insertion. If not, I'd suggest that you either place the content in a CSV file that can be read and parsed, or put the data into a temporary database table that you can query from and act on.



First, you've got to create a custom module which can provide the framework for creating a page. If you're unfamiliar with how to do this, click here to access a great tutorial on the Drupal website. Once you create this custom module, you'll need to use hook_menu to add a menu item, which will call a function that contains your node insertion code.


Node Fields

Basic node fields include anything that comes standard with any Drupal node, such as the following:

$node = new stdClass();
//Main Node Fields
$node->name = "Title";
$node->title = $node->name;
$node->body = "Lorem Ipsum";
$node->type = 'page'; //This can be any node type
$node->created = time();
$node->changed = $node->created;
$node->promote = 0; // Display on front page ? 1 : 0
$node->sticky = 0;  // Display top of page ? 1 : 0
$node->format = 2;  // 1:Filtered HTML, 2: Full HTML
$node->status = 1   // Published ? 1 : 0
$node->language = 'en';


CCK Fields

Standard CCK Fields (Text, Integer)

On most occasions, your node will have CCK fields in addition to the regular node fields given. It's important to be able to upload those as well. Some examples are as follows:

$node = new stdClass();
//Main Node Fields
/* This is a standard CCK text field. Note the array fields here
* If this field is allowed to have more than one entry, you can
* increment the "0" value to the maximum allowed number.
* Also, note how you must always populate the "value" instance
* of the array
$node->my_text_field[0]['value'] = $data['IMAGE_CREDIT'];
/* This is a CCK textarea field. Note how you can also define the 
* format of the textfield to be Filtered HTML, Full HTML etc.
$node->my_text_area[0]['value'] = $data['OFFLINE_CONTENT'];
$node->my_text_area[0]['format'] = 2;


CCK Node Reference Fields

Importing node reference fields are slightly different than the above, in that you need to assign the ['nid'] element of the array instead of the ['value'] element.

$node->my_node_reference_field[0]['nid'] = $node_ref_id;


CCK Time Fields

This is for the CCK Time module The time element is a bit tricky. Instead of inserting it as ['value'], you need to insert the hour, minute, and meridian fields as such:

$node->my_time_field[0]['hour'] = $hour;
$node->my_time_field[0]['minute'] = $minute;
$node->my_time_field[0]['meridiem'] = $meridiem;


CCK File Fields

Many thanks to this drupal post for help on how to import cck filefield files/images. First of all, you want to upload all of your files via FTP onto your server. This will save alot of time during the import process because the system won't have to upload these files as well. Essentially, a function will find the specified file, enter it in the files table, then assign it to your CCK filefield.

//Inside your node creation function
$file = new stdClass();
$file->filepath = "relative-drupal-path-dir/".$filepath;
$node->field_event_speaker_image = array(drupal_add_existing_file($file->filepath));
//Separate function
function drupal_add_existing_file($file_drupal_path,$uid=1,$status=FILE_STATUS_PERMANENT) {
'filename' =>basename($file_drupal_path),
'filepath' =>$file_drupal_path,
'filemime' =>file_get_mimetype($file_drupal_path),
'filesize' =>filesize("/var/www/clients/usni/htdocs/".$file_drupal_path),
'uid'      =>$uid,
'status'   =>$status,
return field_file_load($file_drupal_path);


Taxonomy Fields

When assigning nodes to taxonomy fields, you'll need to have your taxonomy created and know the exact TIDs that you want to assign to your new node. Then you put them into an array as such:

$tags = explode(",", $my_taxonomy_tags);
foreach($tags as $key => $val) {
$taxArr['tax']['tags'][$val] = taxonomy_get_term($val);
$node->taxonomy = $data['tax']['tags'];


Ubercart Product Node Fields

If you're inserting an Ubercart product node, there are a few special fields you may want to import, such as price, shipping dimensions, weight etc.

$node->model = "MODELNUM";
$node->default_qty = 1;   // Set default quantity to 1
$node->pkg_qty = 1;       // Set default quantity to 1
$node->list_price = 45.00;
$node->sell_price = 55.00;
$node->shippable = 1;     // Can this be shipped ? 1 : 0
$node->weight = 16;
$node->weight_units = "oz"; //Could be oz, lb etc.
$node->dim_length = 6;
$node->dim_width = 6;
$node->dim_height = 6;
$node->length_units = "in"; //Could be in, ft etc.

If you've defined price per roles using the Ubercart Price Per Role module, you can also insert prices for individual roles

$node->role_prices[$role_id] = $your_price;


Saving the node

Once you've got your node object fully populated, it's time to save the node.

if ($node = node_submit($node)) {
//Enter Nodewords	
//This is not required, but once you save the node, you can add meta tags via
//the nodewords module
$nodewords['keywords']['value'] = $keywords;
$nodewords['description']['value'] = $description;
nodewords_save_tags(NODEWORDS_TYPE_NODE, $node->nid, $nodewords, TRUE);
drupal_set_message(t("Node ".$node->title." added correctly"));
} else {
drupal_set_message(t("Node ".$node->title." added incorrectly"), "error");



Those are the main issues that we've dealt with in terms of inserting node content. There are most certainly other instances where a CCK/module field requires import in a different way, but hopefully, this can speed up your process of inserting content!