drupal_write_record

Drupal提供了很多API函数,学习这些API函数,需要比较多的时间,但是,一旦学会了,使用Drupal自己的API函数,就会给我们带来很多的方便。drupal_write_record就是这样的一个Drupal API函数。

drupal_write_record($table, &$record, $primary_keys = array())

这个函数包含三个参数:

$table、数据库表的名字,必须定义在schema中。

$record,一个要被插入的对象或数组,这里使用的是引用传递。

$primary_keys,如果没有设置主键,表示新建;如果设置了主键,则表示更新。

 

drupal_write_record的优势,就是将Drupal数据库的插入、更新操作合并成一个。统一了起来。我们来看一下drupal_write_record的源代码:

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;

}

 

实际的drupal_write_record用例,摘自Field validation Alpha1版:

function field_validation_rule_save($values) {

  // save rules data

  if ($values['action'] == 'add') {

    drupal_write_record('field_validation_rule', $values);

    $ruleid = $values['ruleid'];

    if ($ruleid) {

      module_invoke_all('field_validation', 'rule', 'add', $values);

    }

  }

 

  if ($values['action'] == 'edit') {

    drupal_write_record('field_validation_rule', $values, 'ruleid');

    $ruleid = $values['ruleid'];

    if ($ruleid) {

      module_invoke_all('field_validation', 'rule', 'edit', $values);

    }

  }

}

 

此外,Drupal专业开发指南,对此有介绍:使用drupal_write_record()进行插入和更新