Drupal模块部署与更新全攻略
在Drupal开发中,模块的部署、安装、更新和卸载是非常重要的环节。本文将详细介绍如何通过
.info
和
.install
文件来实现这些功能,并以天气信息模块为例进行说明。
1.
.info
文件配置
在Drupal中,
.info
文件是模块的重要配置文件,它包含了模块的基本信息,如名称、描述、依赖项等。以下是
.info
文件的一些关键配置项:
-
features[]
:例如
features[] = comment_user_verification
。
-
settings[]
:这是一个可选的键值数组,用于向主题传递信息。类似于
.NET
应用配置框架中的
<add key="mykey" value="myvalue" />
,在
.info
文件中可以写成
settings[mykey] = myvalue
,主题模块可以使用
theme_get_setting()
函数获取这些设置。
-
engine
:该必填字段指定主题使用的主题引擎。如果未提供,主题将被视为独立主题,即使用
.theme
文件实现。大多数主题应使用
phptemplate
作为默认引擎。
-
screenshot
:这是一个可选字段,指示Drupal主题页面引擎在哪里可以找到主题的缩略图。如果
.info
文件中省略此键,Drupal将使用主题目录中的
screenshot.png
文件。
.info
文件的行可以按任意顺序排列(除了
$Id$
行),但大多数用户会将名称和描述放在首位,以便于阅读和更新。需要注意的是,
.info
文件的内容会被缓存到数据库中,因此Drupal不会注意到任何更改。要清除缓存,可以点击“Configuration➤Performance”中的“Clear all caches”按钮。
2.
.install
文件的作用
如果模块需要新的内容类型、自定义数据库或对环境进行其他更改,如创建目录结构,就需要包含一个
.install
文件。该文件的名称与模块名称相同,扩展名为
.install
。
.install
文件的作用是为模块的安装和卸载提供支持,确保用户在使用和卸载模块时不会留下任何痕迹。
3. 构建
.install
文件
.install
文件与Drupal的钩子系统一起工作,最常见的用途是创建数据库表。以天气信息模块为例,我们需要创建一个表来跟踪用户输入的天气位置信息。以下是创建表的
schema
钩子函数:
function weather_info_schema() {
$schema['weather_info'] = array(
'description' => 'Weather information history.',
'fields' => array(
'hid' => array(
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
'description' => 'Primary Key: Unique history entry ID.',
),
'location' => array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => 'Weather location.',
),
'units' => array(
'type' => 'text',
'length' => 50,
'not null' => TRUE,
'description' => 'Weather unit system.',
),
'language' => array(
'type' => 'text',
'length' => 50,
'not null' => TRUE,
'description' => 'Language in which weather is displayed.',
),
'uid' => array(
'type' => 'int',
'not null' => TRUE,
'default' => '0',
'description' => 'The uid of the user making the entry.',
),
'timestamp' => array(
'type' => 'int',
'not null' => TRUE,
'default' => '0',
'description' => 'A unix timestamp indicating the time the entry was made.',
),
),
'primary key' => array('hid'),
'indexes' => array(
'list' => array('location'),
),
);
return $schema;
}
在这个函数中,首先定义了表的字段,然后可选地定义了键和索引。数组的第一维是要创建的表的名称,这里是
weather_info
。通过返回
$schema
,Drupal模块安装函数会自动处理数据库表的创建。
4. 启用和安装钩子
在Drupal中,模块可以被启用、安装、禁用或卸载。当管理员在模块管理页面勾选模块并点击“Save configuration”按钮时,安装程序会查找
.install
文件中的某些钩子。首先处理
schema
钩子创建数据库表,然后如果模块尚未安装(或已卸载),安装程序引擎会查找
install
钩子并执行它(如果存在),最后执行
enable
钩子。
4.1
Install
钩子
以下是天气信息模块的
install
钩子示例:
function weather_info_install() {
global $user;
// Insert a default weather_info category.
db_insert('weather_info')
->fields(array(
'location' => 'Manchester, NH',
'units' => 'F',
'language' => 'en',
'uid' => $user->uid,
'timestamp' => REQUEST_TIME,
))
->execute();
drupal_set_message(st('Weather information table has been created.'));
}
在这个钩子中,使用
db_insert()
函数插入一条初始记录。同时,还需要使用Fields API创建模块依赖的字段,例如天气位置、语言和单位字段:
// Weather location field
$field = array(
'field_name' => 'field_weather_location',
'type' => 'text',
'translatable' => TRUE,
);
$instance = array(
'field_name' => 'field_weather_location',
'entity_type' => 'user',
'bundle' => 'user',
'label' => 'Weather location',
'widget' => array(
'type' => 'text_textfield',
'weight' => '15',
),
'description' => st('Enter a location on earth for which you would like '
. 'to see weather information presented.'),
);
// Create the field and instance.
field_create_field($field);
field_create_instance($instance);
// Weather language field
$field = array(
'field_name' => 'field_weather_language',
'type' => 'list_text',
'translatable' => TRUE,
'settings' => array(
'allowed_values' => "en|English\nes|Spanish\nde|German\ntr|Turkish\nfr|French\n",
'allowed_values_function' => '',
),
);
$instance = array(
'field_name' => 'field_weather_language',
'entity_type' => 'user',
'bundle' => 'user',
'label' => 'Weather language',
'widget' => array(
'type' => 'options_select',
'weight' => '16',
),
'description' => st('Enter the language in which you would like to see '
. 'weather information presented.'),
'default_value' => array(
array(
'value' => 'en',
),
),
);
field_create_field($field);
field_create_instance($instance);
// Weather units field
$field = array(
'field_name' => 'field_weather_unit',
'type' => 'list_text',
'translatable' => TRUE,
'settings' => array(
'allowed_values' => "F|Fahrenheit\nC|Celsius\nK|Kelvin\nR|Rankine",
'allowed_values_function' => '',
),
);
$instance = array(
'field_name' => 'field_weather_unit',
'entity_type' => 'user',
'bundle' => 'user',
'label' => 'Weather units',
'widget' => array(
'type' => 'options_select',
'weight' => '17',
),
'description' => st('Enter the measurement unit with which you would like '
. 'to see weather information presented.'),
'default_value' => array(
array(
'value' => 'F',
),
),
);
field_create_field($field);
field_create_instance($instance);
4.2
Enable
钩子
enable
钩子的作用是设置模块依赖的系统变量:
function weather_info_enable() {
variable_set('default_location', 'Manchester, NH');
variable_set('default_units', 'F');
variable_set('default_language', 'en');
variable_set('current_location', variable_get('default_location'));
drupal_set_message(st('Weather information default variables have been set.'));
}
5. 模块更改与历史记录插入
创建天气信息历史表后,我们可以添加功能来利用这个新表。每次用户更改其个人资料信息时,插入一条记录到历史表中:
function weather_info_insert_history($location, $language, $unit, $weather) {
global $user;
$fields = array(
'location' => $location,
'language' => substr($language, 0, 2),
'units' => substr($unit, 0, 1),
'uid' => $user->uid,
'timestamp' => REQUEST_TIME,
);
$options = array('return' => Database::RETURN_STATEMENT);
$returned = db_insert('weather_info', $options)
->fields($fields)
->execute();
}
function weather_info_profile_weather_location_validate($element, &$form_state) {
$location = $form_state['values']['field_weather_location']['und'][0]['value'];
$language = $form_state['values']['field_weather_language']['und'][0]['value'];
$unit = $form_state['values']['field_weather_unit']['und'][0]['value'];
if (variable_get('default_location') != $location) {
$weather = weather_info_get_weather($location, 'en');
if ($weather) {
weather_info_insert_history($location, $language, $unit, $weather);
}
else {
form_set_error('field_weather_location[und][0][value]', t('Cannot get weather for %location.',
array('%location' => $location)));
}
}
}
6. 禁用和卸载钩子
禁用和卸载钩子用于撤销启用和安装钩子所做的环境更改,特别是卸载钩子可以删除模块正常使用时生成的信息。
6.1
Disable
钩子
当模块在模块页面上被取消勾选并提交页面时,执行
disable
钩子:
function weather_info_disable() {
variable_del('default_location');
variable_del('default_units');
variable_del('default_language');
variable_del('current_location');
}
这个函数只是从变量表中删除系统变量,虽然不是必需的,但清理是一个好习惯。
6.2
Uninstall
钩子
当模块在卸载页面上被勾选并提交页面时,执行
uninstall
钩子:
function weather_info_uninstall() {
field_delete_field('field_weather_location');
field_delete_field('field_weather_language');
field_delete_field('field_weather_unit');
// Flush the cache to get rid of the user profile page entry
drupal_flush_all_caches();
}
在卸载模块时,需要删除所有创建的字段,并清除缓存。如果使用
schema
钩子创建了表,卸载引擎会自动处理这些表的删除。
在交付模块之前,需要将
.install
文件添加到
.info
文件中,让Drupal知道它的存在:
; $Id$
name = Weather information
description = A block that shows current weather for a particular location.
package = Cool stuff from Brian
core = 7.x
files[] = weather_info.module
files[] = weather_info.inc
files[] = weather_info.install
files[] = tests/weather_info.test
dependencies[] = blocks
configure = /admin/config/weather_info/settings
version = 7.x-1.x
通过以上步骤,我们可以完成Drupal模块的部署、安装、更新和卸载。在后续的开发中,还需要考虑模块的更新问题,确保用户能够方便地升级到新版本。
Drupal模块部署与更新全攻略
7. 更新钩子与模块更新
随着模块的开发,我们肯定会对其进行改进。Drupal有一个更新管理器,它会定期检查Drupal社区网站(drupal.org),查看特定系统上加载的所有模块是否有可用更新。如果你的模块托管在drupal.org上并发布了新版本,所有启用该模块的系统上的更新管理器都会通知管理员有新版本可用。
当你对模块进行功能添加或删除,且只影响模块本身时,只需将新的模块文件放在项目目录中即可。但如果添加的功能影响到系统的其他部分,就需要使用更新钩子,让安装程序引擎知道如何处理新代码。
更新钩子可用于处理多种情况,例如添加新的数据库字段以捕获更多信息、修复错误指定的数据库表、创建存储特定信息的新目录或更改角色权限等。
Drupal的更新引擎会读取
.install
文件,查找需要应用的更新。它会记录每个已安装模块的当前更新版本。当有新的更新可用时,安装程序会查找具有特定名称的更新钩子,该名称遵循以下规则:
- 第1位数字表示Drupal核心兼容性。
- 第2位数字表示模块的主要版本号(例如,模块是7.x - 1.
系列还是7.x - 2.
系列)。
- 后2位数字是从00开始的顺序计数。
以下是一些更新钩子名称的示例:
| 更新钩子名称 | 说明 |
| — | — |
|
weather_info_update_7100()
| 这是使数据库准备好运行天气信息模块7.x - 1.
版本的第一次更新。 |
|
weather_info_update_7000()
| 假设模块有一个在Drupal 6下运行的版本,这是将其升级到与Drupal核心API 7.x兼容所需的更新。 |
|
weather_info_update_7200()
| 这是使数据库准备好运行天气信息模块7.x - 2.
版本的第一次更新。 |
|
weather_info_update_7201()
| 这是使数据库准备好运行天气信息模块7.x - 2.* 版本的第二次更新。 |
8. 创建更新示例
以天气信息模块为例,我们希望保存用户选择新位置时返回的XML流,并将数据库表名改为更具描述性的名称。以下是实现这一目标的步骤:
首先,修改写入数据库的函数:
function weather_info_insert_history($location, $language, $unit, $weather) {
global $user;
$fields = array(
'location' => $location,
'language' => substr($language, 0, 2),
'units' => substr($unit, 0, 1),
'uid' => $user->uid,
'timestamp' => REQUEST_TIME,
'xml' => $weather->asXML(),
);
db_insert('weather_info_history')
->fields($fields)
->execute();
}
这里使用了
asXML()
方法将XML天气对象序列化,并将
db_insert()
函数中的表名改为
weather_info_history
。
接下来,创建更新钩子函数:
/**
* Rename {weather_info} table to {weather_info_history} and add a field to capture
* raw XML data from the weather service.
*/
function weather_info_update_7100() {
db_rename_table('weather_info', 'weather_info_history');
db_add_field('weather_info_history', 'xml',
array(
'type' => 'text',
'size' => 'normal',
'description' => 'Raw weather XML returned.',
)
);
// update all existing records
$result = db_select('weather_info_history', 'h')
->fields('h', array('hid', 'location', 'language'))
->execute();
foreach ($result as $record) {
$weather = weather_info_get_weather($record->location, $record->language);
if ($weather) {
db_update('weather_info_history')
->fields(array(
'xml' => $weather->asXML())
)
->condition('hid', $record->hid, '=')
->execute();
}
}
}
这个函数首先重命名表,然后添加一个新字段,最后读取现有记录并使用天气服务生成的XML更新每条记录。
9. 更新系统的操作步骤
完成
.install
文件的更新后,我们需要将更新后的包交付给用户。具体操作步骤如下:
1.
更新
.info
文件
:由于我们有了新版本的程序,需要更新版本号。新的
.info
文件如下:
; $Id$
name = Weather information
description = A block that shows current weather for a particular location.
package = Cool stuff from Brian
core = 7.x
files[] = weather_info.module
files[] = weather_info.inc
files[] = weather_info.install
files[] = tests/weather_info.test
dependencies[] = profile
configure = /admin/config/weather_info/settings
version = 7.x-1.0
- 放置新模块文件 :将新的模块文件放在项目目录中。
-
触发更新流程
:
- 访问配置页面,更新管理器会检测到有新的模块版本,并显示错误消息。
- 点击“status report”可获取更多信息。
- 点击“database update script”启动更新程序,会出现更新向导。
-
点击“Continue”,会显示所有可用的更新信息,包括
.install文件中的注释和更新编号(如7100)。 - 点击“Apply pending updates”,更新程序会运行所有可用的更新函数(这里只有一个),过程中会显示进度条。
- 更新完成后,会显示状态屏幕。
以下是更新流程的mermaid流程图:
graph LR
A[放置新模块文件] --> B[访问配置页面]
B --> C{检测到新模块版本?}
C -- 是 --> D[点击status report]
D --> E[点击database update script]
E --> F[更新向导]
F --> G[点击Continue]
G --> H[显示可用更新信息]
H --> I[点击Apply pending updates]
I --> J[更新进行中]
J --> K[更新完成,显示状态屏幕]
C -- 否 --> L[无更新]
通过以上步骤,我们可以确保用户能够方便地将模块更新到新版本,同时保证系统的稳定性和数据的完整性。在开发Drupal模块时,合理使用
.info
和
.install
文件,以及各种钩子函数,可以有效地管理模块的部署、安装、更新和卸载过程。
超级会员免费看
8

被折叠的 条评论
为什么被折叠?



