How do I update a node via a custom form? I have built a custom form (in a module) that creates several related nodes in the database when submitted. Now, I need to create a module so that a user can update his/her submitted form data at a later date. Here's my rough plan:

(1) Determine the nodes that the user wants to update via a wildcard in a requested url;
(2) retrieve the required data from the database;
(3) build a form and insert the retrieved database values via the #value property;
(4) bulid a submit function that uses db_update to update the node

Is this the right approach for updating a node via a custom form? Here's my (not working) module code so far:

// Implements hook_menu().
function update_card_menu() {
    $items['update-card/%update_card'] = array(
        'page callback' =&gt; 'update_card_form',
        'page arguments' =&gt; array(1),
        'access callback' =&gt; TRUE,
    );
    return $items;
}

// Database query function.
function update_card_load($nid) {
    $query = db_select('node', 'n');
    $query -&gt; condition('nid', $nid);
    $query -&gt; join('card_number', 'cn', 'n.nid = cn.entity_id');
    $nodes = $query
    -&gt; fields('n', array('nid', 'title'))
    -&gt; fields('cn', array('field_card_name_nid'))
    // This query will get more complex - I need more nodes and more fields
    -&gt; execute();
    foreach ($nodes as $field) {
        $card['nid'] = $field -&gt; nid;
        $card['card number'] = $field -&gt; field_card_number_nid;
    }
    return $card;
}


$card now contains some values I want to populate my update form:

Array ( [nid] => 123 [card number] => 456 )

But how do I get $card into my form builder function, so that I can populate my #value properties from this array? My code does not work.

/**
 * Renderable form array return function.
 */
function update_card_form() {
    return drupal_render(drupal_get_form('update_card_capture'));
}

/**
 * Form builder function.
 */
function update_card_capture($form, &amp;$form_state, $card) {
    $form['nid'] = array(
        '#title' =&gt; t('nid'),
        '#type' =&gt; 'textfield',
        '#value' =&gt; $card-&gt;nid
    );
        $form['card number'] = array(
        '#title' =&gt; t('Card number'),
        '#type' =&gt; 'textfield',
        '#value' =&gt; $card-&gt;card_number
    );
}
You need to use hook_menu() to register the path and callback function, like so:

&lt;?php
function hook_menu() {
  $items['some-path/%node'] = array( // %node will use the node_load() function that's already provided by node.module.
    'type' =&gt; MENU_CALLBACK // This is just a callback item, it will not appear in any "menus"
    'page callback' =&gt; 'drupal_get_form'
    'page arguments' =&gt; array('the_form_function_name', 1) // Where 1 = the %node wildcard
    'access callback' =&gt; 'node_access',
    'access arguments' =&gt; array('update', 1), // The user must be able to update the node
  );
  return $items;
}
?&gt;


Then build a simple form that provides fields to alter on the node, and run node_save() in the submit handler to save any modifications you make to the node.

&lt;?php
function the_form_function_name($form, &amp;$form_state, $node) {
  drupal_set_title('Now editing node ' . check_plain($node-&gt;title));

  // Just store the entire $node object in a custom form property. Easy.
  $form['#node'] = $node;

  // An example form field that we'll use to update the node's title.
  $form['new_title'] = array(
    '#title' =&gt; 'Title',
    '#type' =&gt; 'textfield',
    '#default_value' =&gt; $node-&gt;title,
  );

  $form['submit'] = array(
    '#type' =&gt; 'submit',
    '#value' =&gt; 'Save Node',
  );

  return $form;
}

function the_form_function_name_submit(&amp;$form, &amp;$form_state) {
  $form['#node']-&gt;title = $form_state['values']['new_title'];
  // Save the modified node object (http://api.drupal.org/node_save)
  if (node_save($form['#node'])) {
    drupal_set_message('Updated the node.');
  } else {
    drupal_set_message('Could not update the node.', 'error');
  }
}
?&gt;


This is just sample code – I have not tested, but it should work barring any typos.

You would hit this via: http://example.com/some-path/123 where 123 is the node ID of the node you want to edit.