function drupal_write_record

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

Do not use drupal_write_record() within hook_update_N() functions, since the database schema cannot be relied upon when a user is running a series of updates. Instead, use db_insert() or db_update() to save the record.

Parameters

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

object|array $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.

array $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

bool|int 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

18 calls to drupal_write_record()
CacheTest::testNoneCaching in drupal/core/modules/views/lib/Drupal/views/Tests/Plugin/CacheTest.php
Tests no caching.
CacheTest::testTimeCaching in drupal/core/modules/views/lib/Drupal/views/Tests/Plugin/CacheTest.php
Tests time based caching.
DatabaseStorageController::save in drupal/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
Implements \Drupal\Core\Entity\EntityStorageControllerInterface::save().
DatabaseStorageController::saveRevision in drupal/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
Saves an entity revision.
DatabaseStorageControllerNG::save in drupal/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
Overrides DatabaseStorageController::save().

... See full list

File

drupal/core/includes/schema.inc, line 377
Schema API handling functions.

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();
  $default_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;
    }

    // Skip fields that are not provided, default values are already known
    // by the database. property_exists() allows to explicitly set a value to
    // NULL.
    if (!property_exists($object, $field)) {
      $default_fields[] = $field;
      continue;
    }

    // However, if $object is an entity class instance, then class properties
    // always exist, as they cannot be unset. Therefore, if $field is a serial
    // type and the value is NULL, skip it.
    // @see http://php.net/manual/en/function.property-exists.php
    if ($info['type'] == 'serial' && !isset($object->{$field})) {
      $default_fields[] = $field;
      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.
    if (isset($object->{$field}) || !empty($info['not null'])) {
      $fields[$field] = drupal_schema_get_field_value($info, $fields[$field]);
    }
  }

  // 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;
      }
      else {
        unset($fields[$serial]);
      }
    }

    // Create an INSERT query. useDefaults() is necessary for the SQL to be
    // valid when $fields is empty.
    $query = db_insert($table, $options)
      ->fields($fields)
      ->useDefaults($default_fields);
    $return = SAVED_NEW;
  }
  else {

    // Create an UPDATE query.
    $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;
      }
    }
  }
  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;
}