drupal_write_record

6 common.inc drupal_write_record($table, &$object, $update = array())
7 common.inc drupal_write_record($table, &$record, $primary_keys = array())
8 schema.inc drupal_write_record($table, &$record, $primary_keys = array())

Saves (inserts or updates) a record to the database based upon the schema.

Parameters

$table: The name of the table; this must be defined by a hook_schema() implementation.

$record: An object or array representing the record to write, passed in by reference. If inserting a new record, values not provided in $record will be populated in $record and in the database with the default values from the schema, as well as a single serial (auto-increment) field (if present). If updating an existing record, only provided values are updated in the database, and $record is not modified.

$primary_keys: To indicate that this is a new record to be inserted, omit this argument. If this is an update, this argument specifies the primary keys' field names. If there is only 1 field in the key, you may pass in a string; if there are multiple fields in the key, pass in an array.

Return value

If the record insert or update failed, returns FALSE. If it succeeded, returns SAVED_NEW or SAVED_UPDATED, depending on the operation performed.

Related topics

33 calls to drupal_write_record()

File

includes/common.inc, line 6917
Common functions that many Drupal modules will need to reference.

Code

function drupal_write_record($table, &$record, $primary_keys = array()) {
  // Standardize $primary_keys to an array.
  if (is_string($primary_keys)) {
    $primary_keys = array($primary_keys);
  }

  $schema = drupal_get_schema($table);
  if (empty($schema)) {
    return FALSE;
  }

  $object = (object) $record;
  $fields = array();

  // Go through the schema to determine fields to write.
  foreach ($schema['fields'] as $field => $info) {
    if ($info['type'] == 'serial') {
      // Skip serial types if we are updating.
      if (!empty($primary_keys)) {
        continue;
      }
      // Track serial field so we can helpfully populate them after the query.
      // NOTE: Each table should come with one serial field only.
      $serial = $field;
    }

    // Skip field if it is in $primary_keys as it is unnecessary to update a
    // field to the value it is already set to.
    if (in_array($field, $primary_keys)) {
      continue;
    }

    if (!property_exists($object, $field)) {
      // Skip fields that are not provided, default values are already known
      // by the database.
      continue;
    }

    // Build array of fields to update or insert.
    if (empty($info['serialize'])) {
      $fields[$field] = $object->$field;
    }
    else {
      $fields[$field] = serialize($object->$field);
    }

    // Type cast to proper datatype, except when the value is NULL and the
    // column allows this.
    //
    // MySQL PDO silently casts e.g. FALSE and '' to 0 when inserting the value
    // into an integer column, but PostgreSQL PDO does not. Also type cast NULL
    // when the column does not allow this.
    if (isset($object->$field) || !empty($info['not null'])) {
      if ($info['type'] == 'int' || $info['type'] == 'serial') {
        $fields[$field] = (int) $fields[$field];
      }
      elseif ($info['type'] == 'float') {
        $fields[$field] = (float) $fields[$field];
      }
      else {
        $fields[$field] = (string) $fields[$field];
      }
    }
  }

  if (empty($fields)) {
    return;
  }

  // Build the SQL.
  if (empty($primary_keys)) {
    // We are doing an insert.
    $options = array('return' => Database::RETURN_INSERT_ID);
    if (isset($serial) && isset($fields[$serial])) {
      // If the serial column has been explicitly set with an ID, then we don't
      // require the database to return the last insert id.
      if ($fields[$serial]) {
        $options['return'] = Database::RETURN_AFFECTED;
      }
      // If a serial column does exist with no value (i.e. 0) then remove it as
      // the database will insert the correct value for us.
      else {
        unset($fields[$serial]);
      }
    }
    $query = db_insert($table, $options)->fields($fields);
    $return = SAVED_NEW;
  }
  else {
    $query = db_update($table)->fields($fields);
    foreach ($primary_keys as $key) {
      $query->condition($key, $object->$key);
    }
    $return = SAVED_UPDATED;
  }

  // Execute the SQL.
  if ($query_return = $query->execute()) {
    if (isset($serial)) {
      // If the database was not told to return the last insert id, it will be
      // because we already know it.
      if (isset($options) && $options['return'] != Database::RETURN_INSERT_ID) {
        $object->$serial = $fields[$serial];
      }
      else {
        $object->$serial = $query_return;
      }
    }
  }
  // If we have a single-field primary key but got no insert ID, the
  // query failed. Note that we explicitly check for FALSE, because
  // a valid update query which doesn't change any values will return
  // zero (0) affected rows.
  elseif ($query_return === FALSE && count($primary_keys) == 1) {
    $return = FALSE;
  }

  // If we are inserting, populate empty fields with default values.
  if (empty($primary_keys)) {
    foreach ($schema['fields'] as $field => $info) {
      if (isset($info['default']) && !property_exists($object, $field)) {
        $object->$field = $info['default'];
      }
    }
  }

  // If we began with an array, convert back.
  if (is_array($record)) {
    $record = (array) $object;
  }

  return $return;
}

Comments

As far as I understood, if we

As far as I understood, if we pass the third argument to the function (primary key), it will update the record, if don't pass - it will insert a new record. Is there any function, that automatically determines whether to update a record (if we have a record with such a primary key) or to insert a new record?

Use db_merge()

For a query that will automatically decide whether to insert or update, use db_merge(). See this page: http://drupal.org/node/310085

mysql_insert_id

Hi!

Need your help!

I understood the functionality of this function, which is easy. But I need to know how to get last ID of the table in which a new row has been added? Like in PHP, I can use mysql_insert_id to get the last ID. What would be the criteria here?

Please, help!

Thanx in advance!

Regards!

Helped Myself!

Hi!

I have solved the issue myself. So, thought of putting it here for other beginners like me.

Here is the example:

<?php
   
// Initializing $record array with values.
   
$record = array (
   
"uid" => $user->uid,
   
"ufname" => $form_state ["values"]["name"],
   
"ufdesc" => $form_state ["values"]["desc"],
   
"ufpath" => $path,
   
"ufstatus" => 1,
   
"ufdate" => $time,
    );
   
// Inserting $record (data) into the database. Here $table variable contains the name of the table.
   
drupal_write_record ($table, $record);
   
// Getting the last inserted ID. (ufid) is the primary key of the table in my scenario.
   
$return = $record ['ufid'];
?>

I hope this will help!

Regards!

watchdog notification on missing schema?

While developing a custom module, I noticed drupal_write_record fails silently when the selected table schema is missing from the cache.
I realized a watchdog entry for this event would have saved me some time.

<?php
...
if (empty(
$schema)) {
 
watchdog('system', '%table schema not defined.', array('%table' => $table), WATCHDOG_WARNING);
  return
FALSE;
}
...
?>

watchdog notification on missing schema?

Could not agree with you more ste5ens. Ran into the exact problem myself today and was banging my head against it until stumbling across your post! Thank-you very much indeed!

clumsy documentation: " To

clumsy documentation:

" To indicate that this is a new record to be inserted, omit this argument."
Should be:
"Omit this argument (ONLY) if inserting a new record. This arguement IS NEEDED for record updates."

SAVE_UPDATED doesn't mean a record has been really modified

SAVE_UPDATED is always returned when an update SQL query is performed, even in case no record is actually modified.

Check this bug report:
http://drupal.org/node/602190

For example, if you provide a wrong primary key value and no record is modified drupal_write_record will returns SAVED_UPDATED.

Login or register to post comments