Has Creating Node Reference Fields Programmatically been Solved for 5.x?

newbstah - June 27, 2008 - 16:03
Project:Content Construction Kit (CCK)
Version:5.x-1.7
Component:nodereference.module
Category:support request
Priority:normal
Assigned:Unassigned
Status:active
Description

Hi There,

Have looked at the following places in trying to figure out how to populate a nodereference field programmatically when creating a node with node_save():

How to programmatically create nodereferences
http://drupal.org/node/148022

and

Nodereference field data must be changed after node_load() before node_save($node)
http://drupal.org/node/99837

Unfortunately, these issues are both for 4.x and I'm running 5.17 on php 5 / Drupal 5.x, so I'm not sure that these apply to the situation I'm in. Either way, I've tried what (I think) was suggested and the field just stays blank. The noderef field doesn't show up on a dev load. If I populate it manually, the result looks like this: (this is a print_r)

[field_item_node] => Array
        (
            [0] => Array
                (
                    [nid] => 36
                )

        )

And my most recent of several attempts looks like this:

<?php
$field_nodereference
= array();
$field_nodereference[0]['nid'] = $nodereferenced_nid;

$node = new StdClass();
 
$node->type = 'item';
 
$node->title = $other_node->title;
 
$node->body = 'text in here';
 
$node->field_nodereference = $field_nodereference;
node_save($node);
?>

#1

newbstah - June 27, 2008 - 16:09

Dang! didn't get to finish the above post when I accidently hit return. My apologies!

Wanted to say that I'd be very very way extremely unbelievably so grateful for any help you could extend. Am really at a loss how to proceed. Does anyone have any ideas? I've hit a wall and have no idea what to try next.

#2

newbstah - June 27, 2008 - 21:54

Have more carefully copied what I thought would work from the second link above. I don't know whether there's something faulty in my code or whether the code isn't valid for 5.x.

Here's the array I'm trying to fill:

[field_item_node] => Array
        (
            [0] => Array
                (
                    [nid] => 36
                )

        )

Don't know how to see the code in the form submit handler. Here's the code from the post:

[field_related_blog_posts] => Array
        (
            [nids] => Array
                (
                    [93] => 93
                    [7] => 7
                    [20] => 20
                )

        )

Here's what I tried:

<?php
$field_nodereference
= array('nids' => array());
$field_nodereference['nids'][$nodereferenced_nid] = $nodereferenced_nid;

$node = new StdClass();
 
$node->type = 'item';
 
$node->title = $other_node->title;
 
$node->body = 'text in here';
 
$node->field_nodereference = $field_nodereference;
node_save($node);
?>

Here's the code from the post above.

<?php
/**
* Helper function that attaches a blog post to a project.
*/
function _mymodule_blog_submit($blog_nid, $project_nid) {
 
// Load project node.
 
$node = node_load($project_nid);
 
$field_related_blog_posts = array('nids' => array());

 
// Change CCK nodereference data from load structure to submit structure.
 
foreach($node->field_related_blog_posts as $delta => $item) {
   
// If this blog is already attached to this project, cancel.
   
if ($item['nid'] == $blog_nid) {
      return;
    }

   
$field_related_blog_posts['nids'][$item['nid']] = $item['nid'];
  }

 
// Attach blog post and save project node.
 
$field_related_blog_posts['nids'][$blog_nid] = $blog_nid;
 
$node->field_related_blog_posts = $field_related_blog_posts;
 
node_validate($node);
 
$node = node_submit($node);
 
node_save($node);
}
?>

I've also changed the node reference from a multiselect to a auto complete (which kinda messes up the site.) I noticed that the people who created the Node Factory module are able to populate multiselects. Any ideas what I'm doing wrong?

PS I'll also take any advice on any other part of what I'm trying to do if it's wonky...

Thanks!

#3

newbstah - June 28, 2008 - 04:58

This works for a single select widget - much thanks goes out to clemens.tolbloom, author of the Node factory module.

<?php
$field_nodereference
= array();
$field_nodereference['nids'] = $nodereferenced_nid;

$node = new StdClass();
 
$node->type = 'item';
 
$node->title = $other_node->title;
 
$node->body = 'text in here';
 
$node->field_nodereference = $field_nodereference;
node_submit($node);
node_save($node);
?>

The weird thing is that it's wiped the content_field_nodereference table from the database, but it's finally working. If anyone has any idea why this might be, I'm very curious.

Here's clemens' code. It's in node_factory.module for 5.x.

<?php
case 'nodereference':
          if ( !isset(
$key)) {
           
$key = 'nids';
          }

          if (
$field['multiple'] == 1) {
           
$edit[ $name][$key] = array($value);
          }
          else {
            if(
$field['widget']['type']= 'nodereference_select' || $field['widget']['type']= 'userreference_select') {
             
$edit[ $name][$key] = $value;
            }
            else {
             
// autocomplete ????
             
$edit[ $name] = array(array($key => $value));
            }
          }
?>

#4

calebtr - July 31, 2008 - 20:46

This works for a single select widget ...

Any ideas about getting this to work for multiple nodereferences?

#5

newbstah - August 16, 2008 - 05:59

Here's what I got working for multiselect.

<?php
multiselect nodereference population

$nids
= array();
foreach (
$whatev as $nid) {
 
$nids[$nid] = $nid;
 
$field_noderef_multi['nids'] = $nids;
 
 
$node = new StdClass();
 
$node->type = $newtype;
 
$node->uid = $uid;
 
$node->name = $name;
 
$node->title = $title;
 
$node->status = 1;
 
$node->field_noderef_multi = $field_noderef_multi;

 
node_submit($node);
 
node_save($node);
}
?>

#6

seanmclucas - October 31, 2008 - 18:08

Wow. Thanks. I've been bangin' my head on this for a while...

So far this is the ONLY way i've been able to insert Node References that are set up as select lists using 'node_save'.

<?php


$field_nodereference
= array();
$field_nodereference['nids'] = $nodereferenced_nid;

$node = new StdClass();
 
$node->type = 'item';
 
$node->title = $other_node->title;
 
$node->body = 'text in here';
 
$node->field_nodereference = $field_nodereference;
node_submit($node);
node_save($node);
?>

I still don't understand why this doesn't work, but I guess it has something to so with the array structure...

<?php
$node
->field_nodereference[field_nodereference][nids] = $nodereference_nid;

//OR

$node->field_nodereference[][nids] = $nodereference_nid;
?>

#7

yched - October 31, 2008 - 23:13

Bottomline is : either you create the node through drupal_execute ('fake' form submission), or through a direct api call to node_save.

drupal_execute:
- you go through the validation step : if you provide values that would cause a validation error if you submitted them in the real node form, then your node won't get created. This ensures you don't put invalid stuff in your db.
- slower than a direct node_save
- you need to provide the values as the form (in the case of cck fields, this means 'as the widget') expects them. Can be hard to predict, and if you change the widget for your field, for instance from an autocomplete text box to a select list, your code breaks.

node_save :
- no validation against invalid entries - be sure that your values are correct according to the field's settings
- faster, could be more
- expected format only depends on the field type, so it's "predictable". It does changes between field types, depending on the storage columns they define : array(0 => array('nid' =>12), 1 => array('nid' => 15)) for a noderef field, array(0 => array('value' => 'foo', 'format' => 1), 1 => array('value' => 'bar', 'format' => 1)) for a text field with the 'formatted text' option. Use devel.modue's 'devel load' tab on node pages to find out how your specific field is stored.

 
 

Drupal is a registered trademark of Dries Buytaert.