Hi,
my module is using the insert hook to insert nodes of type question. now i wish to create nodes with out using a node form.

I am guessing i can just create a node object of type question programmatically , alter some of its propertys and then pass it to question_insert($node) to save it. i have found node_save but no method to freshly create node objects . i also found advice to use node_aggragator but i cant find it in the api.

Is this how i should create a node ?

What functions should i use to create the fresh node object ?

Once again thankyou for all the great help. :)

Comments

thomjjames’s picture

Hi,

think node_save is what you want.
http://api.drupal.org/api/function/node_save/5

if you don't pass a node id node_save will assume you want to created a new node and do so.
this will invoke your hook_insert (and all other ones too) so your current hook_insert should be fine.

hope that helps
Tom

______________________________________________
http://teachyourselfdrupal.com
http://codelessons.com
Register your interest now & get 20% off all future orders @ both sites

______________________________________________
http://themelize.me - Premium Drupal & Web Themes

bleak26’s picture

Thank you for the quick reply.

can you also tell me, how do i get the node id for the newly saved node.

Once again thank you.

pdelorme’s picture

the node id is inserted directly in the node...

node_save($node); //insert or update
$nid = $node->nid;

P.

bleak26’s picture

$node = new StdClass();
//creating a bare node

$node->type = 'answer';
//giving it type

$node->status = 1;
//give it a published staus

$node->title = "Step up to the FLava";
//gives title

$node->body = "Body Body body";
//gives body

node_save($node);
//save it and give it the rest of the attributes

thomjjames’s picture

Cool,

glad you've sorted it and posted your "how to" here, i'm sure other users will be interested in this.

cheers
Tom
______________________________________________
http://teachyourselfdrupal.com
http://codelessons.com
Register your interest now & get 20% off all future orders @ both sites

______________________________________________
http://themelize.me - Premium Drupal & Web Themes

sessy’s picture

Shouldn't there be a $node = node_submit($node) before node_save($node)?

dwees’s picture

What I normally do is use an array.

<?php
$node
= array(
 
'title' => $title,
 
'uid' => $uid,
 
'body' => $body,
 
'promote' => 0,
 
etc...

);

if (
$node = node_submit($node)) {
 
node_save($node);
}
?>

Dave

My site: http://www.unitorganizer.com/myblog

Website: http://davidwees.com
Twitter: @davidwees

jimbop’s picture

Just a quick addition that cost me a couple of hours... Multiple cck terms are added as an array with an extra key ['value']. If the values are not hard coded you can add them in a foreach loop:

<?php
 
foreach ($the_array as $key => $value) {
   
$node->field_name[]['value'] = $value;
  }
?>
rocky saggoo’s picture

By this command, Shall I be able to see my blog title on the place of Nod?

adam640kb’s picture

I am currently attempting to create a node in a php file that looks something like this:

include_once('includes/bootstrap.inc');
include_once('includes/common.inc');
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

$node = new stdClass();
$node = array();
$node['type'] = 'nodetype';
$node['uid'] = 5;

//cck fields
$node['field_name'] = array(0 => array('value' => value,'format' => 4));
$node = node_submit($node);
node_save($node);

This works fine but I have read here: http://www.civicactions.com/blog/cck_import_and_update that one should be using drupal_execute() to insert a node, and in this instance I need to be able to tell if the form submitted properly, and using drupal_execute seems to be the only way to do so.

So I in trying code as seen at the link above, whenever I set the uid of the node and use drupal_execute I get a new node, from an anonymous user, not the specified uid.

An example of that:

$node = array('uid'  => 5,'name' => 'name,'type' => 'contenttype',);
$values = array();
$values['title'] = 'title';
$values['promote'] = 1;
$values['status'] = 1;
$values['sticky'] = 0;
             //have tried to set the uid in both $node and $values (as i've seen examples with both).
//$values['uid'] = 3;
//$values['uid'][0]['value'] = 3;
$values['field_somecckfield][0]['value'] = somecckvalue;

drupal_execute('contenttype_node_form', $values, $node);

Again this works, but I get an anonymous user, unelss I use user_authenticate('user', 'pass); for the user I'd like the node assigned to (still ignores assigning the uid) which in this case won't work for my application. Is there a method to assign the uid using drupal_execute()?

bassio’s picture

did you know what was wrong?

mooffie’s picture

but I get an an anonymous user,

Try $value['name'] = 'something';.

I have read here: [...] that one should be using drupal_execute() to insert a node

Please quote the sentence.

I need to be able to tell if the form submitted properly, and using drupal_execute seems to be the only way to do so.

There's node_validate(). I believe I saw a page in the handbooks that describe the process.

orangecoat-ciallella’s picture

Drupal 5.7
I used drupal_execute() to create a partial user profile node when users register. I used form_alter to add a few additional fields to the registration form and to set custom form validation and submission functions on user_register. Everything worked well until I tried to set the "authored by" for the node. Originally, I kept getting the anonymous user as the author, despite trying every combination of name, author, uid on the $values and $node parameters.

I found if I gave the "anonymous users" role the permission to "administer nodes" then it would work, but this is NOT a permission you give to anonymous users. This told me it was a permissions issue, so I kept messing with it.

It seems some of the functions drupal_execute() hooks into (possibly node_submit, node_save, and/or others) use the global $user variable to determine the new node's author. When the user is registering they are still anonymous, so Drupal correctly assigns the anonymous user (uid = 0) to those nodes.

However, I setup a secondary submit function on registration and was able to do things just after the new user account was created. By the time drupal_execute() executed the user already had a new account (created via user_register_submit()), they just weren't logged in. I figured I could populate the global $user variable using a user_load plus the new user's name, execute drupal_execute, and then clear the $user variable. Essentially, temporarily login in the new user, creating their profile node as them, and then logging them out. Since the user must pass through user_validate to get this far I figure it's fairly safe to rely on the username they passed in. (Please let me know if you see any security issues with this whole technique, as I was hesitant to post this code if there's a vulnerability. I wasted about 3 hours working around the anonymous issue, so thought it was worth helping some folks avoid or help come up with a better solution)

In my system_custom.module, within a system_custom_form_alter() function, I call a secondary user_registration submit function

// set the form submit to call the regular user_register_submit() (from user.module)
// and the user_register_submit_custom() (defined in this module)
    $form['#submit'] = array(
      'user_register_submit' => array(),
      'user_register_submit_custom' => array()
    );

The custom function, which executes after the regular user_register_submit() to programmatically save a node

function user_register_submit_custom($form_id, $form_values) {

global $user;
$user = user_load( array( 'name' => $form_values['name'] ) );  // load the new user into the $user variable, using their registration name

$node = array('type' => 'yourContentType'); // create a new node of type uprofile

// some sample CCK fields, as an example of the format for different field types
$values['field_fieldname1']['key'] = $form_values['register_value1'];    // a select (dropdown) form element
$values['field_fieldname2'][0]['value'] = $form_values['register_value2'];    // a textfield form element
$values['field_fieldname3']['keys'] = 1;  // a checkbox element

$values['type'] = 'yourContentType'; // the node's type
$values['status'] = 1; // set the node's status to Published
$values['title'] = $form_values['name']."'s Profile";   // the node's title
$values['body'] = 'whatever body you might want, or else, leave blank'; // the body, not required

// $values['name'] = $form_values['name']; // set the author (i.e. name) of the node equal to the username just registered

$errs = drupal_execute('yourContentType_node_form', $values, (object) $node); // call the function to create the node, node_revisions, and CCK values for the uprofile node type

// if there were any validation errors, drupal_execute will return them, then you have a chance to do something
if (count($errs)) {
  // optional code here
}

$user = drupal_anonymous_user(); // clear the temporary user credentials by setting it to the anonymous user settings

} // end of function user_register_submit_custom

Notes for various skill levels

  • $user = user_load( array( 'name' => $form_values['name'] ) )This is the step where we take the username provided during the registration and basically log that user in temporarily. This might not be such a good idea if you were already logged in
  • Notice I commented out $values['name'] = $form_values['name']. Unless you're already logged in as another user with proper credentials it didn't seem to care what was set here, which was my original problem. It seems to look at who's logged in, not who you say should be the author/owner.
  • The $values['field_xxxxxx'][0]['yyyyy'] all depend on your particular CCK field names and the field types. The easiest way to figure out the correct field names and whether to use ['value'] , ['key'] or ['keys'] is to view the array.
    You can view the contents of the form's array by adding code like this to any of your custom modules
    /**
    * Implementation of hook_form_validate().
    */
    function yourContentType_node_form_validate($form_id, $form) {
    print_r($form);
    }

    Then go to /node/add/yourContentType and press Submit. View the source code and you should see the array. The basic (non-CCK) node fields, like title, body, status, sticky, promote, created will also appear at the top of the array. You can pretty much set any of them using $values['theName']

  • The "yourContentType" value is the content type name, like if you go to admin/content/types and mouse over the content type you'll see the name in the URL admin/content/types/******* Obviously, you'd want to change every instance of "yourContentType" to whatever your content type's short name.
  • Again, if you or your user are already logged in before drupal_execute() runs then you probably don't want or need to mess with the $user variable. Also, if you do other hooks on user_register or for your node type then it's possible you could do a redirect or something that would never return to the custom submit function. In this situation you might end up never closing the temporary login.

Suggestions, questions, and improvements are more than welcome.
OrangeCoat.com

txg0_0’s picture

I meet the same problem as you.
according to you mentioned, becaue of the $user, we get uid = 0, so we can add these code

global $user;
$user = user_load(array('uid') => $account->uid); // or    $user = user_load(array('name') => $account->name);

then we get proper uid

====================
http://aymoo.cn

lionic’s picture

Correct! This IS the solution.

The key is this line. We need to have it so that the $user variable is accessible

global $user

Then we must simply add

$formState['values']['name'] = $user->name;
bacteriaman’s picture

I'm trying to define the user name to a node created programmatically using drupal_execute() via cron, but it insists on inserting uid 0 for anonymous. I have confirmed the user name being passed actually exists in the system. Other fields like the node title are defined correctly as expected.

Any advice would be appreciated.

orangecoat-ciallella’s picture

The only way I found to do this was to temporarily log the user in, as described in my post above. There may still be some security implications, but it works. The reason you keep getting 0 is because if you're not logged in then Drupal correctly adds the node as a user 0 (an anonymous visitor). The code above and my subsequent comments should explain how to do a temporary login and how to submit text, checkbox/radio, select/drop-down box, and node reference fields programatically with drupal_execute(). If this doesn't work for you then post some details of the issue or shoot me a message via the contact form on my profile.
Jim
OrangeCoat.com

bacteriaman’s picture

Thanks for your advice and offer to help.

I ended up doing something different, which made anonymously created nodes perfectly acceptable.

More comments regarding this topic can be found in this thread.

jgoldfeder’s picture

Thanks Ciallella for this helpful information.

ferdly’s picture

I used your second block (only slight variation on Lullabot's Eaton article sited).

I did a simple passthru of some simple variables. I used the 'title'=>'drupal execute title' convention for putting in data (or 'when'=>'de when' if I thought the field length was limited).

I didn't know exactly where to make this happen, but I enabled the "Execute PHP" block and placed it in there and clicked the 'Execute' button.

I got the following warning:

warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'node_form' was given in /home/xxxxxx/public_html/drupal/includes/form.inc on line 358.

Might this be an irregularity of my using 6.x, or might I have done something else wrong?

I looked a that line number and it is a tertiary expression as a functon parameter passing either $callback (if it isset) or $form_id. (This seems internal based on what I did or did not include in my drupal_execute() parameters...)

When I poked in Devel's Variable Editor I see that each content type has a variable: form_build_id_<contentype>

According to the warning it would seem that the 'contenttype_node_form' portion was in error.

In my little test content type, 'drupalnotes', I look in phpMyAdmin and see that the table is called 'content_type_drupalnotes', thus my code uses:
drupal_execute('drupalnotes_node_form', $values, $node);

Yes?

BTW, I am meticulously following the directions of this and Eaton article, and thus am creating $node as an array and passing it; however it is confusing to me that $node is said to be an object (http://drupal.org/node/49768) yet we are passing an array?

Thanks in advance.

--
Brad

--
Brad

orangecoat-ciallella’s picture

Yes, Drupal 6 came with changes to drupal_execute(). Likewise, CCK has changed to the point where a Drupal 6 specific example is necessary. This is modified from the basic code snippet shown in the D6 API to include CCK fields.

Drupal 6 Example Code

$form_state = array();
module_load_include('inc', 'node', 'node.pages');  // new for Drupal 6
$nodeTmp = array('type' => 'story'); // a variable holding the content type

$form_state['values']['type'] = 'story'; // the type of the node to be created
$form_state['values']['status'] = 1; // set the node's status to Published, or set to 0 for unpublished
$form_state['values']['title'] = 'Some Node Title Here';   // the node's title
$form_state['values']['body'] = 'whatever body you might want, or else, leave blank'; // the body, not required

  // the username of the node's author, must be a valid user with access to create this node.
  // Otherwise, see (http://drupal.org/node/178506#comment-726479) above about using user_load() to create nodes as any user, even when not logged in
$form_state['values']['name'] = 'someusername'; 
$form_state['values']['op'] = t('Save');  // this seems to be a required value

// CCK field examples for CCK in D6
$form_state['values']['field_mydropdown']['value'] = 3;    // a select (dropdown, where 3 is the "option" value saved to the db
$form_state['values']['field_myuserref'][0]['uid']['uid'] = 'someusername';  // a user reference example
$form_state['values']['field_mycheckbox']['value'] = 1;  // a checkbox example
$form_state['values']['field_mynoderef'][0]['nid']['nid'] = '[nid:9]';  // a node reference example. In this case, 9 is referring to node 9

  // call the function to create the node, node_revisions, and CCK values.
  // Replace "story" with the name of your form / content type
$errs = drupal_execute('story_node_form', $form_state, (object) $nodeTmp);

  // if there were any validation errors, drupal_execute will return them, then you have a chance to do something
if (count($errs)) {
  // optional code here
}

If you compare the Drupal 5 example to the Drupal 6 example you'll notice quite a few differences.

  • module_load_include('inc', 'node', 'node.pages') is now required, as it eliminates the First argument is expected to be a valid callback, 'node_form' error
  • The second argument changed name in the API and syntax. Notice it is now, $form_state['values']..., instead of $form_values
  • CCK changed syntax of their arrays as well. Remember, you can always go to /node/add/yourContentType and look at the source code of the form. For example, the HTML source for the checkbox would look like <input type="radio" name="field_mycheckbox[value]" which translates to $form_state['values']['field_mycheckbox']['value'] as the array in PHP code.
  • There is a new 'op' field which seems to be required.
  • The D6 API code now shows casting the $nodeTmp array to an object, whereas D5 API left it out. I'm not sure which function, but one of the processing functions must need this value as part of an object. Note: the API used the variable name of $node. I changed it to avoid confusion with the $node variable available within template scopes.

Hope this answers them questions.

OrangeCoat.com

ferdly’s picture

Hi OrangeCoat-Ciallella,

Thanks so much.

I (your code) did create the nodes.

I (your code) did create the related rows in the CCK table "content_type_mycontentype" (and I used "mycontentype" instead of "story" above that).

No errors were returned.

But the actual values that were placed in the cck table rows had NULLs for each field.

I could see them in my list View and when I linked to it, the Title and Body were great, and when I edited the other fields were available (but empty or default). I was able to successfully change those NULLs to other values and post those edits.

I didn't see any "text" example, so I assumed that was not a 6 change, and also used your "view source" tip, and confirmed that, so I entered:
$form_state['values']['field_mytext'][0]['value'] = 'de mytext test1'

The first two were both drop-downs so I used your syntax there, but it failed.

My guess -- but I don't have the chops to find where this happens -- is that there are two separate SQL statements, one to insert the node record and one to insert the cck content type record, and because the problem is with the Values() or the parallel list of column names portions of the INSERT it still executed and the fields were set to the Default: NULL.

So close!...

Okay, I turned the DEVEL SQL echo on, so...

When I submit these CCK lines (which I believe adhere to your example):

$form_state['values']['field_source']['value'] = 1;  
$form_state['values']['field_context']['value'] = 3; 
$form_state['values']['field_when'][0]['value'] = 'de when9'; 

Here is the CCK Table SQL that is successfully run:

INSERT INTO content_type_drupalnotes (vid, nid, field_source_value, field_context_value, field_when_value) VALUES (53, 53, NULL, NULL, NULL)

Since the table name and column names in the SQL match perfectly (and the row is created) it would seem that the error is happening because the 1, 3, and 'de when9' values are not "translating" for some reason.

I am logged on as User1 and I supply the the "$form_state['values']['name']" for User1; and double-checked that every single permissions checkbox is checked for Administrator. I also tried disabling the "Node Privacy by Type" module (even though everything for that was checked for Administrator).

I am committed that if you (and/or others) help me break through this barrier I will meticulously document a "follow along" step-by-step tutorial all the way through a credible example to share with all! (Not that this thread, and this reply in particular, haven't been immensely helpful; my intent is to forestall others at my relative newbie level from needing to bother you mavens again.)

Thanks again for this, and thanks in advance for any additional help.

--
Brad

--
Brad

orangecoat-ciallella’s picture

I could understand how the drop-down value wouldn't validate / "translate" if the value being set isn't an option for the drop-down.

For instance, when I look at field_mydropdown's settings via /admin/content/node-type/story/fields/field_mydropdown/edit
under the Allowed values I have a keyed list

1|Jim
2|Evan
3|Josie

Since the 3 is a valid value for this field it saves 3 in the database and when the node is rendered it shows "Josie" in the drop-down. My drop-down was actually of type "text", so this wasn't the best example because I was actually saving integer values, but it works fine because you can save integer values as text, but not vice versa.

Your text field syntax looks alright. I added text field and text area CCK widgets and looked at the HTML source and it appears the following would be the syntax.

$form_state['values']['field_mytextfield '][0]['value'] = 'some text';
$form_state['values']['field_mytextarea'][0]['value'] = 'some longer text';

If you enabled the text processing option for a text field or text area widget (i.e. you select "Filtered text (user selects input format)" instead of "Plain text") then you'd have to also set that filter value programatically like such:

$form_state['values']['field_mytextfield'][0]['format'] = 1; // set the text field's input format to 1 or "Filtered HTML"
$form_state['values']['field_mytextarea'][0]['format'] = 2; // set the text area's input format to 2 or "Full HTML"

Likewise, if you specify other widget options, like "Number of values:" then the syntax would change. My original example used the default settings of "Plain text" and no multiply values. It appears from the SQL statement you posted that you were using Plain text, so not sure that's the problem, but you might double check your widget settings and the HTML code.

Not sure what else to check because the original code I posted worked for the default "Story" content type in Drupal 6.2 and CCK 6.x-2.0-beta . If you want further verify the syntax Drupal is generating when you do a node/add/yourContentType you could create a form_validate or form_submit hook to print the $form_state and see what it's passing in just before it's saved to the database.

/**
* Implementation of hook_form_validate() for Drupal 6
*/
function yourContentType_node_form_validate($form, &$form_state) {
print_r($form_state);
}

// OR

/**
* Implementation of hook_form_submit() for Drupal 6
*/
function yourContentType_node_form_submit($form, &$form_state) {
print_r($form_state);
}

where you'd replace yourContentType with your content type name

kjay’s picture

I'm not entirely sure but this may help others reading this part of the thread who find that their cck fields fail to save a value, even when the node is created correctly and grabbing the field name from source is all done correctly.

It is possibly going wrong due to forgetting to change the drupal_execute('story_node_form', $form_state, (object) $nodeTmp); line to match the name of your content type value.

I had exactly the same behaviour with a custom content type called appointee and simply changing drupal_execute to:

drupal_execute('appointee_node_form', $form_state, (object) $nodeTmp); solved the issue.

carteriii’s picture

This approach is not working for me with a custom node type, which has been created by my custom module. The code does work just fine if I create a node of type 'story' (exactly like above) but when I change the 'story' references to 'my_custom_node_type" it doesn't work.

I've traced through the call to drupal_execute, and I can see the key difference between 'story' and 'my_custom_node_type', but I'm not sure what to do about it. The $form_state['submit_handlers'] is being set for the story node type, but not for my custom node type. The code to do this is wrapped with an "if" test for isset($form['#submit']), which apparently isn't set for my form.

I think part of my problem stems from my lack of understanding about hook_form and hook_node_form. I have found that hook_form puts the default save & preview buttons on the form, along with the various other content related options such as comment, authoring, & publishing settings. Consequently my custom node type uses hook_form to define its form, and everything looks right to the user. By contrast, hook_node_form does NOT automatically add those additional sections or the save & preview buttons. Using hook_node_form, by default, looks completely wrong to the user and doesn't even allow them to save or preview the content, so I simply went with hook_form.

The code above says to use the story_node_form, and I don't really have an equivalent for my custom node type. Is the difference that hook_node_form must include its own submit element on the form, which would then allow drupal_execute to save my node just fine? But since I'm inheriting the submit button by using hook_form, that's the cause of my problem? Should I have created both a hook_form and a hook_node_form, where hook_node_form just calls hook_form and then adds a submit button?

I feel like I've done just about everything I can to step through all the code and see what's happening, but I'm just missing some practical advice about how my custom node should be defining its form through hook_form and/or hook_node_form. Thanks in advance for any clues.

bacteriaman’s picture

My recommendation would be to first create your custom node module with all the essential hooks.

These can include:

hook_node_info
hook_menu
hook_access
hook_perm
hook_view
hook_form
hook_validate
hook_submit
hook_insert
hook_update
hook_delete
hook_load

Once you confirm everything is working correctly, you can then proceed to implement drupal_execute. Remember the 1st argument must reference the correct form_id (exp. [my_node]_node_form) and pass the form_values array as both the 2nd and 3rd arguments.

drupal_execute($form_id, $form_values, $form_values);

That should do it.

-------------------------------------------------------

"The sting in any rebuke is the truth." - Benjamin Franklin

orangecoat-ciallella’s picture

I'd start out with a custom content type with no extra CCK fields. Here's an example.

$form_state = array();
module_load_include('inc', 'node', 'node.pages');
$nodeTmp = array('type' => 'do_dad');

$form_state['values']['type'] = 'do_dad';
$form_state['values']['status'] = 1;

$form_state['values']['title'] = 'My New Do Dad';
$form_state['values']['body'] = 'Blah Blah Body Goes Here';

$form_state['values']['name'] = 'validUserName';
$form_state['values']['op'] = t('Save');  // this seems to be a required value

$errs = drupal_execute('do_dad_node_form', $form_state, (object) $nodeTmp);

If you can get it to work with the custom content type then add one field at a time until you reach a problem.

You might be right about needing to set additional fields if you're doing something special through hooks. It sounds like you're using drupal_execute with a real visible form, which is not the way I've ever used it. More info on what you're trying to accomplish and we might suggest an alternative or we can look deeper into using drupal_execute.

carteriii’s picture

I actually have done as both of you suggested, creating a custom content type without any extra fields and using node_example.module as my base that includes everything listed above. The form itself does work just fine when used through the interface. However, as I mentioned in my original question, note that hook_node_form is NOT one of the functions Bacteria Man lists, nor is it one that is listed in node_example.module. And as orangecoat-ciallella uses in the example above, 'do_dad_node_form' is passed to drupal_execute (not 'do_dad_form').

So I still don't understand the difference between hook_form and hook_node_form. My hook_form seems to work just fine, but I don't know what hook_node_form should be.

In search for more answers, I have found the Drupal function node_form (http://api.drupal.org/api/function/node_form) which appears to add all the extra "stuff" at the bottom of the form, including the submit button with the #submit handler. This function must be called automatically when using hook_form to display the form, but it is not called automatically when using hook_node_form and passing that to drupal_execute. It appears that I need a hook_node_form that does something like this:

function do_dad_node_form(&$node)
{
    $form = do_dad_form($node);
    <somehow call node_form>
    return $form;
}

Of course hook_node_form isn't really a hook, and doesn't appear in any of the documentation. It just appears to take a name similar to a hook, and it seems to be required to pass to drupal_execute. Interestingly enough, the second to last line of node_form includes this line:

$form['#theme'] = array($node->type .'_node_form', 'node_form');

This makes "hook_node_form" appear to be a theming function? Does that make sense?

Can anyone tell me what it really needs to look like?

Thanks again.

bacteriaman’s picture

There's no such hook as hook_node_form, just hook_form.

I think you might be confusing the module prefix name and the hook suffix. Depending on the defintions in hook_node_info you might have module named "journal_node" so the corresponding call to hook_form would be journal_node_form(), but including "node" in the name is not necessary and in fact should probably be avoided.

-------------------------------------------------------

"The sting in any rebuke is the truth." - Benjamin Franklin

carteriii’s picture

I "solved" my problem. Allow me to elaborate for the benefit of others.

I agree and knew that hook_node_form is not a hook (I even said that in my previous post), but I kept seeing that function name passed to drupal_execute in every example (both in form.inc and here in this thread). Consequently I believed that I needed to have a function named . "_node_form". I did create such a function, generally of the same form as hook_form (like I posted above). I would also try passing only . "_form" to drupal_execute, and that too would fail to work.

I finally just deleted my function definition for . "_node_form", but went ahead and passed that to drupal_execute. Go figure, it works just fine.

I still don't understand how or why I must pass . "_node_form" when that function doesn't exist, but now that it works, I'll just accept it and move on. I guess I was just reading things too literally, seeing what I thought was a function name (even if it wasn't a hook) and assuming I had to have a function of that name.

Thanks for replying and being patient with me.

orangecoat-ciallella’s picture

Yes, the first parameter is not a function name, but rather the form ID of the content type being created. Visit a page like /node/add/do-dad and view the HTML source in your browser. You'll notice a hidden form field value like

<input type="hidden" name="form_id" id="edit-do-dad-node-form" value="do_dad_node_form"  />

Take the "value=" portion and that is what to use as the $form_id parameter for drupal_execute(). Note: even though the content type may appear in the URL as "do-dad" (with a dash), both the content type name in the database "do_dad" and the form ID "do_dad_node_form" use underscores to separate words.

Funkymoses’s picture

I'm getting a really strange error I can't even begin to unpack. The situation: I get this working and am about to move on to constructing some views for the programatically inserted nodes when I discover my sandbox site is giving a WSOD in build/views. After some efforts to repair it I just create a new one.

Now the nodes are getting added and the CCK fields are getting populated... on the first added node. Subsequent nodes get added, but none of the CCK fields are getting in. I'm at a loss here. Any idea what could be going on here?

Funkymoses’s picture

Some additional detail: it's only a problem when I try to do this with node reference fields.

orangecoat-ciallella’s picture

This could be some of the CCK + drupal_execute() issues mentioned below by KarenS (CCK master). She suggested node_save() as an alternative.

I personally have used drupal_execute() with CCK fields on one Drupal 6 project with success. I've not had to use node reference fields in a production environment, but I did post an example above that included a test I did involving a CCK node reference field and drupal_execute(). It went something like this,

  // a node reference example for D6. In this case, 9 is referring to node 9
$form_state['values']['field_mynoderef'][0]['nid']['nid'] = '[nid:9]';

If your code looks like this and it's not working then post info on the CCK, Drupal core versions you're using and the code and maybe we can get it sorted out.

Funkymoses’s picture

Drupal 6.9 and CCK 2.1 here.

I managed to resolve the issue, which does seem like a validation thing as KarenS has described here and elsewhere, but I didn't have to stop using drupal_execute.

I did change the format of this...

  // a node reference example for D6. In this case, 9 is referring to node 9
$form_state['values']['field_mynoderef'][0]['nid']['nid'] = '[nid:9]';

...to this:

   $form_state['values']['field_home']['nid']['nid'] = $nid;

Though I can't remember why or how I came to that. I did change the noderef in question from an autocomplete field to a select field, FWIW.

However, I'm now running up against the date validation issue referenced in the above post from Karen and am trying to get it to work with node_save(). So far, no luck. I'm trying to follow the instructions here but I don't have a recent enough version of PHP (5.1.6) to use the function provided and trying to format a UTC string with just date() isn't working. But that's an entirely different issue.

bacteriaman’s picture

...try creating the node manually via the form. This includes passing all data validation rules. You can then proceed to create the node programmatically taking special care to prepare the form data so that it will pass validation transparently.

I'm not a proponent of using node_save (instead of drupal_execute) to create nodes programmatically because it bypasses hook_nodeapi.

greggles’s picture

This is really helpful. Thanks for providing it.

One thing I found (when trying to figure out how to create an organic group) is that it can be really easy to determine which fields are necessary by adding a line of debugging code and then creating a single node:

In the modules/node/node.pages.inc find node_form_submit:

<?php
function node_form_submit($form, &$form_state) {
 
dsm($form_state);
?>

The dsm is a function from the devel module which is very handy.

Thanks again, orangecoat-ciallella!

--
Growing Venture Solutions | Drupal Dashboard | Learn more about Drupal - buy a Drupal Book

--
CARD.com :)

adam640kb’s picture

Having trouble with ImageField CCK fields, any suggestions on how to format them for use with drupal execute? Do I need to create a fid for the file?

nally’s picture

Thanks orangecoat-ciallella for the D6 version of this. It's helping a lot !

In my particular case, I am trying to import 900 nodes, from a CSV. The sticking point for me is taxonomy.

I have a column in my CSV with values like "one, two, three" or "one, five, three" etc.

So, as part of the import process, I'd like to have these taxonomy terms also generated on the fly.

I've seen the statements below that suggest using node_save, but the only way I can think to import all these taxonomy terms is to use a free tagging taxonomy and allow the processing of the form to occur 'naturally', rather than have to build the taxonomy separately, then extract term numbers, and then set values for node_save.

All this to build up the the question:

Using the field name taxonomy-tags-1 doesn't appear to be working for me.

That is, when I include the following line...

$form_state['values']['taxonomy-tags-1'] = 'testing,tags,interest-tag';

... this method doesn't appear to consume those values and create the new taxonomy terms.

Can you think of a reason why this might be?

Christian Nally - Galiano Island, B.C., Canada - http://sticksallison.com

Christian Nally - B.C., Canada - http://sticksallison.com

nally’s picture

Using Greggles great tip to insert a dsm($form_state); into node.pages.inc

I retrieved the following info:

#
taxonomy (Array, 2 elements)
* 2 (Array, 0 elements)
* tags (Array, 1 element)
o 1 (String, 15 characters ) 1test11,1test12

And deduced that this was the syntax for entering the taxonomy terms in text form :

$form_state['values']['taxonomy'] = array('tags'=>array('1'=>'testingagain'));

... where I'm thinking that '1' is my vocab ID, and 'testingagain' is my new vocab term for this node.

Christian Nally - B.C., Canada - http://sticksallison.com

madhattertech’s picture

+1

This is exactly the code I was looking for. Didn't realize that the 1 in array was the vocabulary.

$form_state['values']['taxonomy'] = array('tags'=>array($vocab_subject => implode(",", $subject_terms) ));

Where $vocab_subject was the vocabulary id, and $subject_terms is an array of terms for the vocabulary.

Thank You!

icstars’s picture

here's another working example with both getting the nid and a cck field and impersonating a user (seems dangerous?). my field required [0] before [value]

$form_state = array();
module_load_include('inc', 'node', 'node.pages');  // new for Drupal 6
$nodeTmp = array('type' => 'organization'); // a variable holding the content type

$form_state['values']['type'] = 'organization'; // the type of the node to be created
$form_state['values']['status'] = 1; // set the node's status to Published, or set to 0 for unpublished
$form_state['values']['title'] = 'AB';   // the node's title

global $user;
$user = user_load( array( 'name' => 'someone' ) );
$form_state['values']['name'] = 'someone'; 
$form_state['values']['op'] = t('Save');  // this seems to be a required value

// CCK text field example for CCK in D6
$form_state['values']['field_organization_sfid'][0]['value'] = '1234';

  // call the function to create the node, node_revisions, and CCK values.
  // Replace "organization" with the name of your form / content type
$err = drupal_execute('organization_node_form', $form_state, (object) $nodeTmp);

echo($form_state['nid']); //print out the new nid

bacteriaman’s picture

I would suggest preserving the current user object and restoring it at the end. For example:

global $user;
$current_user = $user;
$user = user_load(array('name' => 'someone'));
// do whatever is needed
$user = $current_user;
greggles’s picture

This should be done as shown in the impersonating a user safely example.

Both of these examples are potentially quite dangerous.

--
CARD.com :)

bacteriaman’s picture

Absolutely, you are correct. A very good precaution.

mradcliffe’s picture

Better yet, make it a habit not to use $user as variable name. Choose $usr or $poster or something else.

greggles’s picture

There are legitimate cases where you need to impersonate another user - and creating nodes is often one of these - so using the global $user is valid in those cases.

In general, of course, I agree with you. I use $account in general and $user only when my code is purposefully impersonating.

--
CARD.com :)

KarenS’s picture

I don't suggest trying to create nodes that use CCK fields using drupal_execute() -- there are dozens of problems that won't happen if you use node_save() instead (see http://drupal.org/node/128038 for some of the issues). One of the main ones is that there is a core bug that skips validation for all but the first value, which leaves out important processing steps for date fields, optionwidget fields, and other fields that manipulate form values. One of the main reasons for using drupal_execute() is to get validation, but validation is broken in drupal_execute if you're creating more than one node at a time so you won't get it anyway.

I strongly strongly suggest using node_save() instead.

bacteriaman’s picture

There's lots of examples of people using drupal_execute() to programmatically create CCK nodes, but I won't deny it's a potential minefield and not for the faint of heart.

If you're not concerned about other modules and hooks reacting to a node insertion then using node_save() might suffice.

For me using drupal_execute() to create regular nodes has proven to be quite successful. I don't rely on drupal_execute() for validation. Since the node is being created programmatically (i.e. transparently) I insure all the data is pre-validated before insertion.

-------------------------------------------------------

"The sting in any rebuke is the truth." - Benjamin Franklin

icstars’s picture

for others who stumble on this thread... hope this helps.

i attempted to get drupal_execute to work for a very long time. as referenced by karen's link above, the first node bulk inserted in the loop will work fine, but in my case, all after that would be oddly corrupted (optionwidget values would only have the first character and nodereference fields would link to node 1 even when they were not specified). this behavior is due to static variables being used which were designed to prevent forms from being validated multiple times, the problem is that we want the same "type" of form to validate on each drupal_execute, but this does not happen. i applied the fix 260934 and all seemed good. the problem then was that automatic node titles were failing, inserted nodes would all take the title of the first node created in the loop. looking at the node that automatic node titles received there were "_error_element" references next to the 'value' element on each field. i gave up on drupal_execute at this point.

node_save seems to be working. the only major issue was phone cck fields which this http://drupal.org/node/146882 issue refers to. i changed their database field attribute to allow nulls like the other cck fields and everything is working.

a few points on this that are interesting. 1 - your source data can have yet to be defined taxonomy terms, this will read them into the node, create the terms, and link them (this was the primary reason i stayed with drupal_execute so long, i didn't realize you could do free tagging with node_save). 2 - this shows how to do node references and 3 - get the node id of the newly created node.

my code shows how to load nodes from content stored in a local temp table. i am creating a contact cck type and the process to integrate with salesforce (http://drupal.org/node/455838)

<?php
include_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
module_load_include('inc', 'node', 'node.pages');

$queryPopQueue = "select * from custom_contact_insert where drupal_node_id is null limit 50";
$queryResult db_query($queryPopQueue);
while (
$data = db_fetch_object($queryResult)){
   
$node->type = 'contact';
   
node_object_prepare($node);
   
$node->uid = 1;
   
$node->title = $data->field_contact_first_name_value . ' ' . $data->field_contact_last_name_value;
   
$node->body = "";
   
$node->teaser = "";
   
$node->filter = variable_get('filter_default_format', 1);
   
$node->format = FILTER_FORMAT_DEFAULT;
   
$node->language = '';
   
$node->revision = 0;
   
$node->promote = 0;
   
$node->created = time();
   
$node->comment= 0;
   
   
$node->taxonomy = array('tags' => array('11' => ($data->categories)));
   
$node->field_contact_first_name[0]['value'] = $data->field_contact_first_name_value;
   
$node->field_contact_last_name[0]['value'] = $data->field_contact_last_name_value;
   
$node->field_contact_job_title[0]['value'] = $data->field_contact_job_title_value;
   
$node->field_contact_organization[0]['value'] = $data->field_contact_organization_value;
   
$node->field_contact_organization_r['nid']['nid'] = '463'; //this is a sample hard coded value
   
$node->field_contact_account_sfid[0]['value'] = $data->field_contact_account_sfid_value;
   
$node->field_contact_sfid[0]['value'] = $data->field_contact_sfid_value;
   
   
$node->field_contact_email_optout[0]['value'] = 'false';
   
$node->field_contact_phone_optout[0]['value'] = 'false';
   
   
$node->field_contact_add1_city[0]['value'] = $data->field_contact_add1_city_value;
   
$node->field_contact_add1_country[0]['value'] = $data->field_contact_add1_country_value;
   
$node->field_contact_add1_zipcode[0]['value'] = $data->field_contact_add1_zipcode_value;
   
$node->field_contact_add1_state[0]['value'] = $data->field_contact_add1_state_value;
   
$node->field_contact_add1_street[0]['value'] = $data->field_contact_add1_street_value;
   
$node->field_contact_add1_type[0]['value'] = 'Work';
   
   
$node->field_contact_add2_city[0]['value'] = $data->field_contact_add2_city_value;
   
$node->field_contact_add2_country[0]['value'] = $data->field_contact_add2_country_value;
   
$node->field_contact_add2_zipcode[0]['value'] = $data->field_contact_add2_zipcode_value;
   
$node->field_contact_add2_state[0]['value'] = $data->field_contact_add2_state_value;
   
$node->field_contact_add2_street[0]['value'] = $data->field_contact_add2_street_value;
   
$node->field_contact_add2_type[0]['value'] = 'Home';
   
   
$node->field_contact_mobile_phone[0]['value'] = $data->field_contact_mobile_phone_value;
   
$node->field_contact_home_phone[0]['value'] = $data->field_contact_home_phone_value;
   
$node->field_contact_work_phone[0]['value'] = $data->field_contact_work_phone_value;
   
$node->field_contact_asst_phone[0]['value'] = $data->field_contact_asst_phone_value;
   
   
$node->field_contact_email1[0]['value'] = $data->field_contact_email1_email;
   
$node->field_contact_email2[0]['value'] = $data->field_contact_email2_email;
   
$node->field_contact_email_asst[0]['value'] = $data->field_contact_email_asst_email;
   
   
$node->field_contact_assistant[0]['value'] = $data->field_contact_assistant_value;
   
$node->field_contact_notes[0]['value'] = $data->notes;
     
   
node_save($node);
   
$nid = $node->nid;
    unset(
$node);
   
   
//update status and drupalid in the queue
   
$queryUpdate = "update custom_contact_insert set drupal_node_id = '$nid', status = '1' where id = '" . $data->id . "'";
   
db_query($queryUpdate);
}
?>
icstars’s picture

value attribute is incorrect for email fields:

$node->field_contact_email1[0]['email'] = $data->field_contact_email1_email;
$node->field_contact_email2[0]['email'] = $data->field_contact_email2_email;
$node->field_contact_email_asst[0]['email'] = $data->field_contact_email_asst_email;

tetramentis’s picture

Thanks a lot for the example of adding free tags! worked perfectly!
$node->taxonomy = array('tags' => array('11' => ($data->categories)));

Also, I have a question regarding taxonomy someone may help me with.

I have a two-level hierarchical taxonomy of the form:

term 1
--term 2
--term 3
term 4
term 5

I have all the necessary tid/vid mappings, and need to import 1k of nodes - assigning them to specific sub-terms of 'term 1'.

This is how I do it: $node->taxonomy[$tid] = array('tid' => $tid, 'vid' => '1', 'name' => $name);

It works, but strangely not only the required sub-term is selected, but also all the top-level terms (terms 1, 4 and 5 in my example). Why does that happen, and how can I avoid that?

tbfisher’s picture

there is code on http://drupal.org/node/128038 to fix the validation issue, works well for import scripts creating multiple nodes with CCK fields using drupal_execute()

orangecoat-ciallella’s picture

An additional note about how to populate a CCK Node Reference form field as part of a programatically submitted node.

It seems when a CCK Node Reference form field is processed the processing function looks for the a token like [nid:#] (where # is a valid node id). The submitted value will probably be something like The Node's Title [nid: 3] but the processor ignores the title portion and uses the token to correctly store the nid in the database.

I had a node reference field called Tour and this format worked for adding a reference to node id

$values['field_tour'][0]['node_name'] = '[nid:'.$aValidNid.']';  // populate the node reference with a token like [nid:3]

See my prior comment above for a full example, which shows example formats for programatically submitting text box values, select (drop-down) values, checkboxes (and radio buttons) values.
OrangeCoat.com

awjrichards’s picture

i'm not sure i follow this example -
i have a node type of mls_listing, a reference field called field_mls which references a node type of mls_feed. i've tried a bagillion different ways of doing this but nothing seems to work. what exactly is supposed to go into the array index where you have 'node_name'? it seems like:

$values['field_mls'][0]['mls_feed'] = '[nid:' . $nid . ']';

should work, but it's not... any suggestions?

thanks a lot!
arthur

orangecoat-ciallella’s picture

If I remember correctly, ['node_name'] is the required value used by the CCK node reference module.

In your case, I believe you'd use

$values['field_mls'][0]['node_name'] = '[nid:' . $nid . ']';

where $nid should be the node id of the referenced node.

Look at the way a node reference field works normally on a /node/add/someType form. You'll notice as you type the name of a node it will search for the node by title and then ends up putting something like "The title of the Node Here [nid:123]" in the text field via AJAX

I assume the CCK node reference field just processes the string value in the form textfield and if it sees the pattern [nid:*] in the string it uses the number specified. So, technically I think you could set the value to 'Blah Blah Blah [nid:234] and it should still work still recognize node 234 as the referenced node.

OrangeCoat.com

farzan’s picture

Definitely solution is this:
drupal_execute()

There is a very good and useful article in Lullabot.com that was extremely useful to me.
http://www.lullabot.com

Here it is:
http://www.lullabot.com/articles/quick_and_dirty_cck_imports

Hope it is useful.

chrisirhc’s picture

I had a problem of newly created nodes created under uid of 0, or an anonymous user.
Initially I kept trying to insert the uid into the node. I ended up with inserting 'name' for the node after reading the example at a website. Somehow, that works but uid doesn't.

I used the following to insert the new node of custom content type.

    global $user;

    $node = array('type' => 'cont_sentitems', 'name' => $user->name);
    $values['title'] = $subject;
    $values['body'] = $body;
    $values['recipients'] = $to_string;
   
    drupal_execute('cont_sentitems_node_form', $values, $node);

Hope this benefits people who encounter the same problem as me and have yet to find a solution or ended up doing this another way.

xxparanormalxx’s picture

so i've got all this down. now suppose i wanted to included the taxonomy as well. how would i do that? i'm trying basically do an import of data that already matches to my current taxonomy...i haven't been able how i could add data to my node before posting in order to get it to post taxonomy data too.

orangecoat-ciallella’s picture

It sounds like you're asking how to add taxonomy terms to a node programatically.

If so, I'd suggest trying the following. As an example, lets assume you have a node of type Book and you want to add to it a taxonomy term of "Fiction", where Fiction has a term ID (tid) of 22 and it part of the vocabulary "Book Type" with a vocabulary ID (vid) of 1. Also assume the vocabulary allows for multiple select and no free tagging.

If you go to the normal /node/add/book page you can look at the HTML source and see something like

<select name="taxonomy[1][]" multiple="multiple" ....
<option value="22">Fiction</option>

or if you use print_r($node) on _nodeapi() hook or print_r($form_values) with a _validate() hook you'd see something like this

[taxonomy] => Array
        (
            [1] => Array
                (
                    [22] => 22
                )

        )

So, without actually testing this I'm going to suggest the syntax to add a tag or tags to a node programatically for multiple select, no free tagging vocabulary would be

$values['taxonomy'][1][] = 22;

OR

$values['taxonomy'][1][22] = 22;

Again, where 1 = the vid of your vocabulary and 22 is the tid of your term.

I'm not sure if either or both of these would work, so this is just pointing you in a direction. Also, the syntax for free tagging or no multiple select could very well be different.

In general, if you look at the the "name" attribute of a form element on the /node/add/yourType page's HTML then it should provide insight into what to use following $values. Also, using print_r() within the _validate() _submit() or nodeapi() hooks should show you what the array of values looks like after Drupal has built it.

OrangeCoat.com

netbear’s picture

Thanks a lot, orangecoat-ciallella, this is very usefull.
My question is: if i create several nodes at a time with this method and one of them have not passed validation( we have $err) but will the data be inserted in db or the process will be like if that was done by submitting node form(incorrect data is not inserted in db) and what will be with other nodes?
Thanks one more time!

http://webdruid.ru - for russians
http://imagency.org - with english version

orangecoat-ciallella’s picture

According to the Drupal 5 API, drupal_execute is "the programmatic counterpart to drupal_get_form". The code for drupal_execute calls drupal_process_form, which calls validation functions and returns on errors. To to me that suggests if an error is encountered then no data would be inserted into the database, just like when validation fails through a regular node form.

If you want to test I'd suggest creating a form validate hook for the node type being submitted and generate a form error by calling form_set_error()
OrangeCoat.com

crystaldawn’s picture

Wouldnt this be the easiest way to do this? It doesnt do validation, but if its an automated task, do you really need validation to begin with? I would expect your automated function to do validation before the node object is run through node_save(). drupal_execute is cumbersome and really unnecessary when programmatically creating node content. It allows you to not only add new nodes, but edit them as well if you replace $node->is_new with a nid instead. It also lets you set the author without any hassles at all which is a real pain in the xxxxxxxxxx with the drupal_execute() method.

<?php
  $node
->is_new = TRUE//If this is a new entry, add this.  Otherwise replace it with $node->nid
 
$node->type = 'story'; //Can be any content type you have
 
$node->status = 1//Optional if this is an existing node
 
$node->title = 'tester'//Optional if this is an existing node
 
$node->uid = 1//Optional if this is an existing node.
 
$node->field_whatever[0]['value'] = 'kkkkkkkkkk'//This is a CCK field
 
node_save($node);  //Actually save or edit the node now
  //For Drupal 5 only  //Grab the NID in case you need it after a NEW entry is created
 
$rows = db_fetch_object(db_query("SELECT id FROM sequences WHERE name='node_nid'"));
 
$node->nid = $rows->id
 
//For drupal 6 only //Grab the NID in case you need it after a NEW entry is created
 
$node->nid = db_insert_id('node', 'nid');
?>
bacteriaman’s picture

Your approach circumvents the system and should be avoided.

drupal_execute, while not for the faint of heart, works well when implemented correctly and insures all tasks associated with node insertion are performed correctly.

-------------------------------------------------------

"The sting in any rebuke is the truth." - Benjamin Franklin

adam640kb’s picture

Is there any way to update a node with drupal_execute? I've went with nmd's method, as it's the only way I've been able to update a node in this way. I've explained my issues with using drupal_execute() here.

bacteriaman’s picture

I've never tried it before, but it should be possible to update a node with drupal_execute.

Again, you need to account for all the other things that go on behind the scenes when creating or updating a node. For example hook_nodeapi's need to respond to a node insertion or update, etc.

I realize that doing something the compliant way takes longer (sometimes MUCH longer), but in the long run you'll be happy you spent the time.

-------------------------------------------------------

"The sting in any rebuke is the truth." - Benjamin Franklin

orangecoat-ciallella’s picture

wdmartin posted an example of using drupal_execute to update a node programatically in Drupal 6, so yes it's possible.

However, wdmartin's example uses an extra $form_state['node'] variable, which I didn't find to be necessary. Here's a link to my slightly modified working example which cuts out a lot of the casting between arrays and objects when updating a node with drupal_execute()

I'll try to post a definitive example here when I get feedback from wdmartin about whether the $form_state['node'] is absolutely necessary.

mchaplin’s picture

Should that link to your example be this?

http://drupal.org/node/293663#comment-1056271

Summit’s picture

Subscribing,
Wandering if somebody already made nodes programmatical, using the taxonomies (taxonomy_xml output as basis for the amount of nodes needing to build?
And using taxonomy_xml information to fill the node_body, so the programmatical framework works as a template?

greetings,
Martijn

yangke’s picture

<?php
 
//For drupal 6 only //Grab the NID in case you need it after a NEW entry is created
 
$my_node->nid = db_insert_id('node', 'nid');
?>

isn't working for me, but node_save does return the complete node object just created so you can do:

<?php
 
//For drupal 6 only //Grab the NID in case you need it after a NEW entry is created
 
$my_node_nid = $my_node->nid;
?>

to get the node nid of the created node.

xjm’s picture

Wish I'd found this information eight months ago rather than muddling through it on my own.

nedjo’s picture

This core function is working example of how to programmatically create a node using node_save():

http://api.drupal.org/api/function/blogapi_blogger_new_post/

notebene’s picture

subscribe

stoptime’s picture

My issue was that I had a form made entirely of cck fields to process in my module. After tons of var_dump'in and what not, I've come up with something worth exploring, because it works (at least for me). While it's unfinished, it will hopefully give other developers some clues. Here's the function (to place in your module). Couple notes:

1. I only wanted to process the 12 fields from the actual form on the web page. But limiting it to this, I bypass any errors from the other hidden form elements that Drupal puts in there (tokens and such). I do it this way because I'm lazy and just wanted to loop over everything instead of hard-coding the form name elements.
2. I intentionally assign a title to the node, based on the combined values of the first and last name.

<?php
/**
  * Process the form (cck handles validation)
  */
function my_module_form_submit(&$form_id, &$form_state) {
   
module_load_include('inc', 'node', 'node.pages');
    global
$user;
   
$node = new StdClass();
   
$node->type = 'your type';
   
node_object_prepare($node);  // not sure if this is needed or not
   
$node->uid = $user->uid;
   
$node->status = 0// change to 1 to publish
   
$node->comment = 0// allow comments?
   
$node->promote = 0;      // promote to front page?
    // work with the first x many fields from the form (avoid processing stuff like tokens)
   
$total_fields = 12; // change this to however many form fields you want to work with, or hard-code instead of loop
   
$i = 0;
    foreach(
$form_state['values'] as $key => $value) {
        if (
$i < $total_fields) {
           
$node->$key = array(array('value' => $value[0]['value']));
           
$i++;
        }
    }
   
$node->title = 'Entry from: ' . $node->field_first_name[0]['value'] . ' ' . $node->field_last_name[0]['value'];
   
node_save($node);
   
// if there's a nid now, then we saved it
   
if ($node->nid) {
        echo
"Node saved with id of: " . $node->nid;
    } else {
        echo
"Node failed to save.";
       
var_dump($node);
        unset(
$node);
        exit();
    }
}
?>
adamo’s picture

I had all kinds of problems trying to programatically create nodes containing autocomplete nodereference fields via drupal_execute. I was looping through a table in an external DB, then building a node and executing drupal_execute for each record. The CCK fields would only get validated during the first call to drupal_execute. Apparently there is a long standing bug in core that causes this.

Anyway, wrapping everything in the Batch API solved the problem for me.

yejezkel’s picture

Could you please specify: "Wrapping in the Batch Api"

brendoncrawford’s picture

The DrupalORM module easily allows for doing this. Assuming the node type was "page"...

<?php
$newNode
= orm('Page')->create();
$newNode->setTitle('hello world');
$newNode->body = 'foobar';
$newNode->field_some_cck_field[0]['value'] = 'foo bar';
$newNode->save();
?>

The module can be found at http://drupal.org/project/orm.

liorm’s picture

I'm trying to search, from a php-filtered node:
<?php

$guid = 'pla_d9674436-9511-41b8-8c87-ce2962afcf22';
$nodes = orm('Videoclip')->find(array(
'Videoclip.field_guid' => $guid ));
>

videoclip is a type I added, and has the field guid

but:
i get an SQL error. seems the WHERE clause is not built propery. to fix, you need to change orm_finder.php, line 160 to:
elseif ($schemaInst->isCCK($table, $field)) {
$tableRaw = $table;
$table = $this->buildCckTableRef($fieldParts);

$tableType = self::TABLE_TYPE_CCK;
$field = $schemaInst->getCCKCode($tableRaw, $field);

}
thanks
Lior

lelizondo’s picture

I'm trying to add terms to several nodes during cron, the nodes are created during cron also. I have an array with the tags, for example:

<?php
$tags
= array('tag1', 'tag2', 'tag3');
?>

The problem is that I don't know how to add those tags to the node, I've tried:

<?php
foreach($tags as $tag) {
 
taxonomy_node_save($node, $tag);
}
?>

And the tags are saved, but I'm getting hundreds of duplicated tags.

Can someone please tell my how to do this? I'm lost..

Luis

bacteriaman’s picture

Be aware with Drupal 6 the call to node_submit() has been removed from node_invoke() and hook_submit() no longer exists. This could affect how data is processed and massaged prior to saving.

I was reminded of this fact today while porting a D5 module to D6, which programmatically creates a node via node_save().

lelizondo’s picture

Actually this was really easy, how could I not see this before? All I had to do was:

$category->tags = implode(", ", $entry->tags);
$node->taxonomy = array('tags' => array('2' => ($category->tags)));

where '2' is the vocabulary id where I want to save the tags; and then save the node with node_save($node)

Luis

neofit’s picture

Now what is the current stand? I want to create a node programmatically using Drupal 6.17 and how should I proceed? Use drupal_execute() or node_save()? Any working code sample?

Jaypan’s picture

You do realize what thread you are posting in right?

bacteriaman’s picture

There's no "current stance" for creating nodes programmatically. If you need to simply create nodes, use node_save(). If you're trying to mimic node form submission, use drupal_execute().

neofit’s picture

Thanks for your answer. Well what I want to do is parsing an XML file and creating nodes from this data, so I guess it is what you call "mimicing node form submission"?

johnmcgeechan’s picture

They all ultimately use cache_clear_all. I have a client that has tens of thousands of nodes and over a million hits a month. I need to execute on a daily basis a script that can potentially update/insert up to 15,000 nodes at a time. If I use node_save/drupal_execute, it will take forever as it chugs through all the potential hooks for the 20/30 odd modules that have nodeapi hooks (and others) AND what's worse it will attempt a cache_clear_all after every single update ! (My site does use the drupal cache as well as caching the opcode in xcache, ).

In short, none of the solutions are workable for me. My approach is going to be to create/update the records manually ie insert into the node tables, node revision tables etc and accept that the data is good data ie pre-sanitised and that no other hooks/drupal processing will be invoked as I am bypassing the usual Drupal methods for inserting.

Don't get me wrong, i don't like it, it's ugly and will probably have to change when they upgrade, but if anyone has some better suggestions for my particular scenario and the volumes of inserts/updates I need to make, can they please give suggestions, I really am all ears (eyes).

johnmcgeechan is a web developer with http://simpleritsolutions.com use contact form to contact me directly

wizonesolutions’s picture

Look into the batch API. Works well for stuff like this.

FillPDF Service - http://fillpdf-service.com - Hosted solution for FillPDF

johnmcgeechan’s picture

er..no..that also uses node_save

johnmcgeechan is a web developer with http://simpleritsolutions.com use contact form to contact me directly

kroshp’s picture

Hi,

How to create a node with custom fields default values. I dont see any respnse on the web?

ex :
i have a content type "mytype" with a field "myfield" with default value "mydefaultvalue"

$node = new stdClass();
$node->type = "mytype";
$node->title = "mytitle";
node_object_prepare($node);
node_save($node);

and myfield dont have "mydefaultvalue"

Thanks

Jaypan’s picture

$node->myField = $defaul_value;

xjm’s picture

If it's a CCK field, the field is an array. You'll want something like
$node->field_myfield[0]['value'] = $default_value;

chales’s picture

For everyone working on bulk adding nodes and having weird quirks with your CCK fields please read about this core issue regarding the form validation static variable, http://drupal.org/node/260934

I spent a lot of time fighting with my custom node creation from a CSV file thinking the whole time it was something wrong with the date formatting because date errors were the only error feedback I received.

After I figured out the problem was in form validation I was able to solve my problem in the same method described in that case, specifically look at http://drupal.org/node/260934#comment-1148384


DrupalVoodoo
Summit’s picture

hi,
i think that the best way for creating nodes from à csv files is through node-import or feeds.

greetings,
Martijn

lelizondo’s picture

Just to update this with a method to do this with Drupal 7 and the new Field API

Just the important part:

$new = new stdClass();
$new->type = "some_type";
$new->title => "Some title";
$new->uid = 1;
$new->field_some_cool_field_description['und'][0]['value'] = "this is a description for this node";
$new->field_my_node_reference_field['und'][0]['nid'] = 3545; // the nid of the node you want to reference to
node_object_prepare($new);
save_node($new);

Luis

pmagunia’s picture

Thanks Luis. Your code worked for me. Just a slight correction:

I think the last line of the code you posted should be:

<?php
node_save
($new);
?>

without the php brackets of course.

sachinwable’s picture

Here is the solution to your problem.

http://www.learn-drupal.in/cck/how-to-create-a-drupal-node-programmatica...

This post described it very nicely.

Thanks

-
SachinW