Drupal向自定义表中添加新列的最佳方法

时间:2020-03-05 15:25:29  来源:igfitidea点击:

通常需要创建特定于模块的自定义表来存储持久数据。
Drupal提供了一组与此相关的挂钩。
其中最常用的是hook_schema()和hook_update_N()。

第一个hook,hook_schema()以PHP数组的形式保存表的结构。
由于Drupal 7,因此不再需要在hook_install()/hook_uninstall()中显式调用Drupal_install_schema()/Drupal_uninstall_schema()。

当第一次启用模块时,将解析hook_schema中定义的表的结构,并为预期用途创建所需的表。

然而,实时用例有时需要在模块启用后向表中添加列(或者更改表)。
在这种情况下,hook_update_N()起作用。

以下面的代码为例,

function my_module_update_7001(&$sandbox) {
  $spec = array(
    'type' => 'int',
    'unsigned' => TRUE,
    'not null' => TRUE,  
  );
  db_add_field('my_table', 'my_column', $spec);
}

这段代码只是将一个名为"my_column"的整数列添加到表"my_table"中。
运行步时更新.php(https://example.com/update.php). 数据库层API会根据需要更改表(在本例中是添加列)。

需要注意的是,同样的列定义也需要添加到hook_schema()中。
因为有可能在另一个站点重新安装模块。

处理这种情况的最佳方法是在hook_schema()中主要定义schema数组,并在hook_update_N()中重用相同的数组。

/**
 * Implements hook_schema().
 */
function my_module_schema() {
  $schema = array();
  $schema['my_module_node_properties'] = array(
    'fields' => array(
      'nid' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'vid' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'my_column' => array(
        'type' => 'int',
        'size' => 'tiny',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'new_column1' => array(
        'type' => 'int',
        'size' => 'tiny',
      ),
      'new_column2' => array(
        'type' => 'int',
      ),
    ),
    'primary key' => array('vid'),
    'indexes' => array('table_id' => array('vid', 'nid')),
  );
  return $schema;
}
/**
 * Add column1 and column2 fields to table {my_module_node_properties}
 */
function my_module_update_7004() {
  $table = 'my_module_node_properties';
  $schema = drupal_get_schema_unprocessed('my_module', $table);  
  foreach (array('new_column1', 'new_column2') as $field) {
    db_add_field($table, $field, $schema['fields'][$field]);
  }
}

上面的代码可以被认为是与我们所讨论的主题最相关的。
表{myu module_node_properties}最初有nid、vid和myu列作为字段。
后来需要添加新的_column1和新的_column2.
相同的定义已经添加到hook_schema中,在hook_update()中,我们使用drupal_get_schema_unprocessed()API从统一源代码获取字段规范,并最终将其传递给db_add_field()。
当然,我们也可以使用module_invoke()API来获取模式,但是drupal_get_schema_unprocessed()是一个包装函数,除了调用module_invoke()来获取模式外,它还进行模式值检查。