Skip to main content

Drupal node load references : Drupal 7

An article from ComputerMinds - Building with Drupal in the UK since 2005
12th Jul 2011

Steven Jones

Senior Developer
Hey, you seem to look at this article a lot! Why not Bookmark this article so you can find it easily in the future?

In Drupal 6, if you called node_load then what you'd be returned would be your own copy of the node to change and modify as you pleased, but in Drupal 7 this was changed. By default, what you actually get back from a node_load is essentially a reference to a global singleton for that node. This has the interesting side effect of meaning that if you change anything in the node object, you are probably changing everyone else's copies of that node too. This is explained in this issue: http://drupal.org/node/154859

So, why should you care? Well, in the right circumstances data loss is really easy!

For example, add a file field to a node type, and allow users to select whether to display files when viewing a node. Now, create a new node, and add a file and uncheck the display checkbox. So, when viewing the node normally, no file is shown.

Now, imagine the following code runs:



// Load up the node with files on it.
$node = node_load(1);

// Render the node.
$rendered = node_view($node);

// Later, decide you want a 'fresh' copy of the node.
$fresh_node = node_load(1);

// Save the fresh node.
node_save($fresh_node);

Now go and edit your file in Drupal, where has your uploaded file gone?

Well, the call to node_view means that file.module directly unsets the files that shouldn't be displayed. But, in my code, this node is effectively global, so when I call my second node load, it's not 'fresh' at all, I just get back a reference to the node that's had the file removed, so calling node_save on it was a very bad idea.

Note that the node_view and node_save don't have to be in the same code, they could be in different modules, that know nothing of what the other is doing.

I'd like to know what the solution here is, one solution might be to clone the node when we get it back from node_load, but that was removed from D6, so it seems silly to add it back everywhere it gets used. Or, you could try to only clone it when the data in the node will be changed, but that will be pretty much every time we do anything with the node, and because of the way Drupal works, things could be changed even when we don't think it would be.
It seems like the only safe solution is to clone most times, but core doesn't do this, so you'll still run into issues like the one outlined above.

Thoughts?

Hi, thanks for reading

ComputerMinds are the UK’s Drupal specialists with offices in Bristol and Coventry. We offer a range of Drupal services including Consultancy, Development, Training and Support. Whatever your Drupal problem, we can help.