Creating nodes programmatically that have CCK image fields in Drupal 6

Sun, Oct 18, 2009 by Afraaz

When creating nodes programmatically it's easy enough to give the node a
title, body, and type by using the following:


$node = new stdClass();
$node->title = 'title';
$node->body = 'body text';
$node->type = 'type';

These are simple properties that ALL nodes will have. What about nodes with CCK fields attached to them? Well for text fields we can simply use the following:


$node = new stdClass();
$node->title = 'title';
$node->body = 'body text';
$node->type = 'type';
$node->$field_name[0]['value'] = 'TEXT'

Where $field_name can take place of the internal CCK field name (field_XXX_XXX)

That covers the text fields but what about images? Here's a little background on the situation that was put infront of me. I had images on a different server which I needed to attach to an image field on one of our content types. So I used a combination of cURL and a CCK function in order to attach the images to the nodes.

First we'll start with the function that uses cURL in order to save the images to our server.


/**
* Allows us to save images from the phonedog webservice
*
* @param $img - The path of the image file
* @param $fullpath - The path to where the image will be saved
*
* @return none
*/
function modulename_save_image($img, $fullpath){
  $ch = curl_init($img);
  curl_setopt($ch, CURLOPT_HEADER, 0);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
   curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
   $rawdata = curl_exec($ch);
   curl_close ($ch);
   if(file_exists($fullpath)){
     unlink($fullpath);
   }
   $fp = fopen($fullpath, 'x');
   fwrite($fp, $rawdata);
   fclose($fp);
}

This function will take a URL to the image and will save the image in a directory of your choosing. When I used this function I decided to use the temp directory of the Drupal instance. IE:


variable_get('file_directory_temp', '/tmp');

Thhis function will save all your images in your temp directory. Now that you have all your images in the tmp directory you can begin to save the node.

I used the following to save images to nodes:


$node = new stdClass();
$node->title = 'title';
$node->body = 'body text';
$node->type = 'type';
$filepaths = array('/tmp/foo.jpg', '/tmp/bar.jpg');
foreach ($filepaths as $filepath) {
  $field = field_file_save_file($filepath, array(), file_directory_path() .'/'. $directory);
  $node->$field_name[] = $field;
}
$node = node_submit($node);
node_save($node);

In the above code the $directory variable can be a sub folder for your images just so you can keep them organized. The $field_name variable is again the internal CCK field name (field_XXX_XXX). This method will support fields that allow for multiple images as well. The $filepaths variable in the above example is hard coded, of course you can create a function that will return an array of image paths.

Well that's how one would go about saving images to nodes programmatically. Please
feel free to let me know if there's a better way of doing the same thing.

The interweb my ~ away from ~

Badger posted on December 7, 2009 3:32 pm

I can't use:
$field_name = 'field_text';
$node->$field_name[0]['value'] = 'TEXT';
I get "PHP Fatal error: Cannot use string offset as an array ..."

Any ideas?

Peter posted on November 13, 2009 8:06 am

Thanks alot for the post! Really helped! I think the proper way to create a node via code is to use drupal_execute like:

drupal_execute('node_form', $form_state, $node);

Matt posted on November 10, 2009 6:22 pm

Hey,

Thanks for the code. What if I'd like to use an image already in the right place? That is, I don't want to copy the image at all, but just get the array generated from this function.

Thanks,
~Matt

admin posted on October 19, 2009 5:12 pm

The node_submit call just prepares the node object for the node_save call. Using the node object it returns, you can pass this into node_save which will allow other modules to modify the node object using hook_nodeapi.

admin posted on October 19, 2009 5:04 pm

Cool thank you. I'll look into using drupal_http_request.

Drupal Theme Garden posted on October 19, 2009 9:31 am

Thanks for this useful article.
Can you, please explain a bit:
$node = node_submit($node);

dalin posted on October 19, 2009 5:17 am

I find drupal_http_request() to be a much better choice than CURL. It's much easier to use and there's no dependency on a PHP module that may or may not be there.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <img> <h2>
  • Lines and paragraphs break automatically.

More information about formatting options