Drupal向自定义表中添加新列的最佳方法
通常需要创建特定于模块的自定义表来存储持久数据。
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()来获取模式外,它还进行模式值检查。