如果您正在为 WordPress 编写插件,您几乎肯定会发现需要在 WordPress 数据库中存储一些信息。您可以存储两种类型的信息:
- 设置信息——用户在首次设置您的插件时输入的用户选择,通常不会超出该范围(例如,在标签相关插件中,用户关于侧边栏标签云格式的选项)。
设置信息通常使用 WordPress 选项 机制 进行存储。 - 数据——随着用户继续使用您的插件而添加的信息,通常是与帖子、分类目录、上传文件和其他 WordPress 组件相关的扩展信息(例如,在统计相关插件中,与您网站上的每个帖子关联的各种页面浏览量、来源和其他统计数据)。
数据可以存储在单独的 MySQL/MariaDB 表中,该表必须创建。但在着手创建一个全新的表之前,请考虑是否可以将您的插件数据存储到 WordPress 的 Post Meta(即自定义字段)中。Post Meta 是首选方法;在可能或实际的情况下请使用它。
本文介绍如何让插件自动创建 MySQL/MariaDB 表来存储其数据。请注意,作为遵循此处步骤的替代方案,您可以让插件用户在安装您的插件时运行安装脚本。另一种方法是让用户自行执行 SQL 查询,使用类似 phpMyAdmin 的工具。但这两种选项都不太令人满意,因为用户很容易忘记运行安装脚本或搞砸查询(而且他们可能没有 phpMyAdmin 可用)。
因此,建议您按照以下步骤让您的插件自动创建数据库表:
- 编写一个创建表的 PHP 函数。
- 确保 WordPress 在插件激活时调用该函数。
- 如果您的插件新版本需要不同的表结构,则创建一个升级函数。
创建数据库表
让您的插件自动创建数据库表的第一个步骤是在您的插件中创建一个 PHP 函数,该函数向 WordPress MySQL/MariaDB 数据库添加一个或多个表。出于本文的目的,我们假设您想将此函数命名为 jal_install。
数据库表前缀
在 wp-config.php 文件中,WordPress 网站所有者可以定义数据库表前缀。默认情况下,前缀为“wp_”,但您需要检查实际值并使用它来定义您的数据库表名。该值位于 $wpdb->prefix 变量中。(如果您正在为 WordPress 2.0 之前的版本开发,则需要使用 $table_prefix 全局变量,该变量在 2.1 版本中已弃用)。
因此,如果您想创建一个名为 (前缀)liveshoutbox 的表,您的表创建函数的前几行将是:
function jal_install () {
global $wpdb;
$table_name = $wpdb->prefix . "liveshoutbox";
}
创建或更新表
下一步是实际创建数据库表。而不是直接执行 SQL 查询,我们将使用 wp-admin/includes/upgrade.php 中的 dbDelta 函数(我们需要加载此文件,因为它默认不加载)。dbDelta 函数检查当前的表结构,将其与所需的表结构进行比较,然后根据需要添加或修改表,因此它对于更新非常有用(有关如何使用 dbDelta 的更多示例,请参见 wp-admin/upgrade-schema.php)。请注意,dbDelta 函数相当挑剔。例如:
- 您必须在 SQL 语句中将每个字段放在单独的一行。
- PRIMARY KEY 一词和主键定义之间必须有两个空格。
- 您必须使用关键字 KEY 而不是其同义词 INDEX,并且必须至少包含一个 KEY。
- KEY 后面必须跟一个空格,然后是键名,再是一个空格,然后是左括号、字段名和右括号。
- 您不能在字段名周围使用任何撇号或反引号。
- 字段类型必须全部为小写。
- SQL 关键字(如 CREATE TABLE 和 UPDATE)必须为大写。
- 您必须指定所有接受长度参数的字段的长度。例如 int(11)。
有了这些注意事项,以下是我们函数中的下一行,它将实际创建或更新表。您需要将您自己的表结构替换到 $sql 变量中:
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
name tinytext NOT NULL,
text text NOT NULL,
url varchar(55) DEFAULT '' NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql );
注意: 上面我们设置了表的默认字符集和排序规则。如果我们不这样做,某些字符在保存到我们的表中时可能会转换为问号。在本例中,我们使用 $wpdb::get_charset_collate() 获取字符集和排序规则。该函数是在 WordPress 3.5 中引入的,如果您需要支持之前的版本,则需要自己创建字符集/排序字符串(您可以复制该函数的源代码)。
添加初始数据
最后,您可能想向刚刚创建的表中添加一些数据。以下是如何做到这一点的示例:
$welcome_name = 'Mr. WordPress';
$welcome_text = 'Congratulations, you just completed the installation!';
$table_name = $wpdb->prefix . 'liveshoutbox';
$wpdb->insert(
$table_name,
array(
'time' => current_time( 'mysql' ),
'name' => $welcome_name,
'text' => $welcome_text,
)
);
注意: 有关使用 WPDB 的更多信息,请参见 wpdb 类。 在这种情况下,我们使用 $wpdb->insert,因此我们的数据将自动转义。如果您需要使用其他方法(如 $wpdb->query),最好在将查询传递给数据库之前通过 $wpdb->prepare 函数运行变量,以防止安全问题,即使我们在本函数中定义了 $welcome_name 和 $welcome_text 并且知道其中没有 SQL 特殊字符。
版本选项
另一个极好的想法是添加一个选项来记录您的数据库表结构的版本号,以便在需要更新表时稍后使用该信息:
add_option( "jal_db_version", "1.0" );
整个函数
此函数已完成。让我们看看它的全部内容。请注意,版本号现在存储在全局变量中。
<?php
global $jal_db_version;
$jal_db_version = '1.0';
function jal_install() {
global $wpdb;
global $jal_db_version;
$table_name = $wpdb->prefix . 'liveshoutbox';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
name tinytext NOT NULL,
text text NOT NULL,
url varchar(55) DEFAULT '' NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta( $sql );
add_option( 'jal_db_version', $jal_db_version );
}
function jal_install_data() {
global $wpdb;
$welcome_name = 'Mr. WordPress';
$welcome_text = 'Congratulations, you just completed the installation!';
$table_name = $wpdb->prefix . 'liveshoutbox';
$wpdb->insert(
$table_name,
array(
'time' => current_time( 'mysql' ),
'name' => $welcome_name,
'text' => $welcome_text,
)
);
}
调用函数
现在我们已经定义了初始化函数,我们希望确保 WordPress 在 WordPress 管理员激活插件时调用此函数。为此,我们将使用 activate_ 操作钩子。如果您的插件文件是 wp-content/plugins/plugindir/pluginfile.php,您将在插件的主体中添加以下行:
register_activation_hook( __FILE__, 'jal_install' );
register_activation_hook( __FILE__, 'jal_install_data' );
有关更多详细信息,请参阅 Function_Reference/register_activation_hook。
添加升级函数
在插件的生命周期中,您可能需要在新版本中更改插件的数据库结构。为此,您需要在插件中创建更新代码,以检测已安装新版本并升级数据库结构。最简单的方法是将代码添加到我们刚刚创建的 jal_install 函数中。
因此,假设上述函数用于创建插件的 1.0 版数据库,而您现在正在升级到 1.1 版以使 URL 字段更宽(从 55 个字符改为 100 个字符)。您需要将以下行添加到 jal_install 函数的末尾,以检查版本并在必要时进行升级:
<?php
global $wpdb;
$installed_ver = get_option( "jal_db_version" );
if ( $installed_ver != $jal_db_version ) {
$table_name = $wpdb->prefix . 'liveshoutbox';
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
name tinytext NOT NULL,
text text NOT NULL,
url varchar(100) DEFAULT '' NOT NULL,
PRIMARY KEY (id)
);";
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql );
update_option( "jal_db_version", $jal_db_version );
}
您还需要更改文件顶部的全局 $jal_db_version 变量,当然您还希望更改上面创建的初始化部分以使用新的表结构。
自 3.1 版本以来,通过 register_activation_hook() 注册的激活函数在更新插件时不会被调用。因此,要在插件升级后运行上述代码,您需要在另一个钩子上检查插件的数据库版本,并在数据库版本过时时手动调用该函数。如下所示:
function myplugin_update_db_check() {
global $jal_db_version;
if ( get_site_option( 'jal_db_version' ) != $jal_db_version ) {
jal_install();
}
}
add_action( 'plugins_loaded', 'myplugin_update_db_check' );
资源
有关插件开发的进一步阅读,请查看 Plugin Handbook,这是一个全面的插件资源列表。您还可能发现来自 wp-hackers 邮件列表 的这篇帖子很有帮助:WordPress Hackers Mailing List: Answer to Plugin Requires Additional Tables。另请参阅:Post meta vs separate database tables。