WordPress 插件更新机制详解及最佳实践
WordPress 本身并不提供原生插件更新流程,开发者需要自行实现。这包括更新数据库中的版本号以及必要时创建新的选项。
WordPress 插件的版本号应存储在两个地方:插件主文件中的常量和数据库中的选项。这使得能够检测自上次插件更新以来数据库选项是否已更新。
更新选项时,开发者应注意不要覆盖用户的选择。如果数据库中不存在某个选项,则应创建它;如果已存在,则不应覆盖它。
对于存储为数组的选项,开发者可以使用 PHP 函数 array_merge()
来确保所有键都已定义,并且不会引入任何不存在的选项。这也确保如果用户更改了旧选项,则会保留其值。
几周前,我收到一封关于 WP Photo Sphere(我开发的一个 WordPress 插件)的邮件。问题很大:更新插件导致某些安装程序崩溃。经过一番调查,我发现问题源于插件使用的选项:这些安装程序没有为我添加的新选项提供任何默认值。
这些值非常重要,所以我需要一种方法来创建默认值。但是,与我的想法相反,WordPress 没有提供任何原生方法来处理更新过程。
这就是我想写这篇教程的原因。首先,我们将准确了解为什么我们需要更新过程以及为什么 WordPress 不提供此类过程。然后,我将向您展示如何正确创建自己的过程来更新您的选项。
插件更新过程的重要性
通常,仅更改文件不足以正确更新某些内容。例如,当您手动将 WordPress 文件更新到新版本时,平台会要求您点击一个按钮来更新数据库。
假设您在插件中使用选项。随着插件的发展,您在新版本中将需要更多选项。在用户首次激活插件时创建新选项很容易,您只需使用激活钩子即可。
例如,让我们看一下以下代码:
function my_awesome_plugin_activation() { update_option('my_awesome_plugin_option', 'default value'); } register_activation_hook(__FILE__, 'my_awesome_plugin_activation');
如果您不熟悉使用 update_option()
来代替 add_option()
,请不要担心,我们稍后将在讨论如何处理更新过程时进行解释。
如果您想要一个新的选项,或者如果您在新版本中更新了现有选项的值,则需要更新已经使用您的插件的用户数据库,因此我们需要一个在更新后立即调用的函数。
激活钩子可能有点令人困惑。毕竟,当您自动更新插件时,它会被停用并重新激活,因此我们可以预期会调用此钩子。但事实并非如此。
更准确地说,它曾经是,但 WordPress 在 3.1 版中停止了此行为。开发团队解释了这个选择,您可以在 Make WordPress Core 博客上阅读完整的解释。主要原因是它并非每次都被调用,因为如果用户手动更新插件,则可以跳过激活钩子。
因此,WordPress 没有提供在插件更新后自动调用函数的默认方法。这就是为什么您需要构建自己的过程。
如何处理更新过程
在本教程的这一部分中,我将向您展示如何在插件更新后自动调用给定函数。我们将在下一部分中看到如何正确处理现有选项的更新以及新选项的创建(在同一个函数中)。
我们方法的全局原则是,我们将插件的版本号存储在两个地方:插件主文件中的常量和数据库中的选项。
数据库中的数字将存储用户当前安装的版本,而常量中的数字是当前版本。如果这两个数字不同,则自上次插件更新以来数据库选项尚未更新,因此我们需要执行此操作。
在这种情况下,我们将调用一个更新所有必要选项的函数。此函数还更新存储在数据库中的版本号:这样,我们就不会过度调用此函数。
既然我们已经介绍了我们将要做什么,那么是时候编写代码了!首先,在插件主文件中添加一个常量定义,并将您的当前版本号作为值。为了防止任何问题,我们测试它是否尚未存在。
function my_awesome_plugin_activation() { update_option('my_awesome_plugin_option', 'default value'); } register_activation_hook(__FILE__, 'my_awesome_plugin_activation');
通常,插件版本使用数字标识,但是,如果您使用其他系统,请随意使用它。这里的唯一约束是为每个版本或至少为每个需要更改数据库(新选项、新默认值等)的版本提供唯一的标识符。
我们现在需要编写一个函数来检查数据库是否需要更新。此函数将比较前面定义的常量与当前存储在数据库中的值。为此,我们将确保我们的函数在任何地方都被调用,使用 plugins_loaded
动作,一旦所有插件加载完毕就会触发。
if (!defined('MY_AWESOME_PLUGIN_VERSION')) define('MY_AWESOME_PLUGIN_VERSION', '3.4.1');
此函数将很简单。我们检索存储在数据库中的版本号,就像任何其他选项一样,并将它与常量进行比较。如果这些值不同,我们将调用 my_awesome_plugin_activation()
函数。
function my_awesome_plugin_check_version() { } add_action('plugins_loaded', 'my_awesome_plugin_check_version');
现在,我们需要澄清一些问题。首先,如果选项在数据库中尚不存在怎么办?如果选项不存在,get_option()
将返回 false,这与您的版本号不同,因此将调用该函数。
那么我们为什么要调用激活函数呢?明确地说,我们可以创建一个新的函数,专门用于更新过程。但是,如果您这样做,您会看到这个新函数将与激活非常相似,因为更新选项可以与创建选项的方式相同。
您可以在上面调用的激活函数中做任何您想做的事情。但是,有一件事是必要的,那就是更新存储在数据库中的版本号。这样,我们不会在每次加载页面时都调用我们的函数。
function my_awesome_plugin_activation() { update_option('my_awesome_plugin_option', 'default value'); } register_activation_hook(__FILE__, 'my_awesome_plugin_activation');
请注意技巧:我们不使用 add_option()
,只使用 update_option()
。事实上,如果选项尚不存在,update_option()
将创建它。如果它存在,它将把它的值更新为指示的值。这就是为什么我们可以毫无问题地将我们的激活函数用作更新函数。
更新选项
更新任何选项都可以与我们更新版本号的方式相同:您可以调用 update_option()
,然后就完成了,即使这是 WordPress 第一次看到该选项。
但是,我们并不总是想更新选项值。事实上,如果您使用选项,通常是为了让您的用户个性化设置。通过使用 update_option()
,您将在每次更新插件时覆盖用户的选择,这不是我们想要做的。
在上面,我们看到如果选项不存在,get_option()
将返回 false。我们将使用此行为来测试我们想要更新的选项是否存在于数据库中。如果是这种情况,我们什么也不做。否则,我们创建该选项。
if (!defined('MY_AWESOME_PLUGIN_VERSION')) define('MY_AWESOME_PLUGIN_VERSION', '3.4.1');
请注意,此测试对于我们不想覆盖的选项是必要的。在某些情况下,我们可能想要这样做,考虑版本号,我们当然不想保留旧值!
您应该知道 WordPress 允许数组存储我们的选项的值,并且创建它们并不比创建其他选项更难。例如:
function my_awesome_plugin_check_version() { } add_action('plugins_loaded', 'my_awesome_plugin_check_version');
如果您需要多个设置,使用数组是一个好主意。这样,您不会在数据库中使用大量条目,并且您限制了另一个插件使用相同名称的选项的机会。但是,当我们考虑更新过程时,这可能会导致问题。
为了理解原因,假设您有一个数组作为选项,带有一些键。您的用户肯定会个性化这些值。使用我们上面做的测试,我们只能在选项不存在时创建它,并且这些选择不会被覆盖。这看起来很简单,但是如果您想在数组中创建一个新键怎么办?
如果选项存在于数据库中,则前面的代码不会创建它,因此您的新键将不存在。但是,如果我们删除条件,则数组将在每次新更新时检索其默认值。不太理想。幸运的是,有一个解决方案!
首先,我们定义一个包含选项默认值的数组(如果存在新键)。
if (MY_AWESOME_PLUGIN_VERSION !== get_option('my_awesome_plugin_version')) my_awesome_plugin_activation();
然后,我们检索当前存储在数据库中的数组。
function my_awesome_plugin_activation() { update_option('my_awesome_plugin_option', 'default value'); } register_activation_hook(__FILE__, 'my_awesome_plugin_activation');
现在我们可以使用 PHP 函数 array_merge()
,将我们的默认值数组作为第一个参数,将用户的数组作为第二个参数。这样,我们将得到一个包含 $default
数组中定义的所有键的数组,并且我们不会有任何不存在的选项。如果用户更改了旧选项之一,则会保留其值。使用 array_merge()
,我们始终保留最新的定义。
if (!defined('MY_AWESOME_PLUGIN_VERSION')) define('MY_AWESOME_PLUGIN_VERSION', '3.4.1');
最后,我们使用 update_option()
将结果存储在数据库中。
function my_awesome_plugin_check_version() { } add_action('plugins_loaded', 'my_awesome_plugin_check_version');
我们快结束了,但是如果函数第一次执行,我们现在需要修复一个您可能会遇到的错误。
此函数在插件激活时被调用,这就是我们想要的。但是,在这种情况下,选项尚不存在,因此 get_option()
返回 false。问题是将 false 用作 array_merge()
的参数会导致错误。
我们想要的是简单的,如果选项不存在,我们希望 $option
是一个空数组。为此,我们可以使用 get_option()
的第二个参数,它表示要获取的默认值(为了不返回 false)。
if (MY_AWESOME_PLUGIN_VERSION !== get_option('my_awesome_plugin_version')) my_awesome_plugin_activation();
结论
一旦您仔细阅读了它,处理 WordPress 插件的更新过程并不复杂。但是,如果您使用选项,这很重要,因为没有初始化选项可能会导致一些问题。
目前,WordPress 没有提供处理插件更新的原生方法。事实上,考虑到我们上面列出的问题,如果我们看到有一天引入了这种类型的功能,则应该以类似于本教程的方式实现它。
您可以在这里获取我的示例插件的代码。将此代码视为实现您自己的 WordPress 插件更新过程的框架。如果您有任何反馈,请在下面的评论中告诉我。
WordPress 插件更新常见问题解答 (FAQ)
定期更新 WordPress 插件至关重要,原因如下:首先,更新通常包含可以增强网站性能的新功能和功能。其次,更新通常会修复可能危及网站安全的错误和漏洞。最后,更新确保与最新版本的 WordPress 兼容,确保您的网站平稳高效地运行。
为了确保安全更新,请务必在启动更新过程之前备份您的网站。这样,如果在更新过程中出现任何问题,您可以轻松地将您的网站恢复到之前的状态。此外,建议在将其应用于您的实时网站之前,在暂存网站上测试更新。
如果插件更新失败,第一步是从备份中恢复您的网站。然后,尝试确定失败的原因。这可能是由于与另一个插件或主题冲突,或者与您的 WordPress 版本存在兼容性问题。一旦您确定了问题,您可以自己解决它,或者联系插件开发者寻求帮助。
WordPress 具有内置功能,允许您自动更新插件。您可以通过转到 WordPress 仪表板中的“插件”部分,选择您想要自动更新的插件,然后单击“启用自动更新”来启用此功能。
是的,如果插件更新导致您的网站出现问题,您可以回滚插件更新。有几个可用的插件,例如 WP Rollback,允许您轻松地恢复到插件的先前版本。
高级 WordPress 插件的更新方式与免费插件类似。但是,您需要拥有有效的许可证密钥才能访问更新。输入许可证密钥后,您可以从 WordPress 仪表板更新插件。
如果您正在管理多个 WordPress 网站,则可能需要花费大量时间为每个网站单独更新插件。更有效的方法是使用 WordPress 管理工具(例如 ManageWP 或 MainWP),它允许您从单个仪表板管理所有网站的更新。
如果您想禁用特定插件的自动更新,可以使用 Easy Updates Manager 等插件。此插件允许您控制网站上每个插件的自动更新。
在更新插件之前,您可以通过访问 WordPress 插件目录上的插件页面来检查其与您的 WordPress 版本的兼容性。在这里,您会找到有关插件与不同 WordPress 版本的兼容性的信息。
如果插件更新破坏了您的网站,第一步是从备份中恢复您的网站。然后,停用导致问题的插件。如果您无法访问您的 WordPress 仪表板,您可以通过 FTP 停用插件,方法是重命名 wp-content/plugins 目录中的插件文件夹。停用插件后,您可以排除故障或联系插件开发者寻求帮助。
以上是WordPress插件以正确的方式更新的详细内容。更多信息请关注PHP中文网其他相关文章!