问题描述

问题

我们都在这样的情况下,这个网站上的很多问题都需要这样的解决方案。您必须更新数据库,自动插入大量数据,转换 meta_keys 或类似的东西。

当然,在基于最佳做法的运行系统中,这不应该发生。

但是,像我这样做,我很乐意听到你的个人解决方案,这个问题,为什么你选择你的。

问题

如何在 (运行)WordPress 安装中实现 one-time 脚本?

这里的问题主要是由于以下原因:

  • 插入数据的脚本不应该运行多于一次
  • 需要大量资源的脚本不能在无法监视的时候运行
  • 他们不应该意外跑跑

我问的原因

我有自己的做法,我将在答案中张贴。因为我不知道这是否是最好的解决方案,我想知道你的。此外,这是一个在其他问题的背景下被问到很多次的问题,而且收集资源的方法很有用。

期待从你那里学习:)

最佳解决方案

我为自己使用的组合:

  • 一个专用于 one-time 脚本的文件
  • 使用瞬态停止脚本不止一次地意外运行
  • 使用 capability-management 或 user-control 来确保脚本只是由我运行。

Structure

我在我的 include-folder inc 中使用一个文件 (onetime.php),该文件包含在 functions.php 中,并在使用后从中删除。

include( 'inc/onetime.php' );

该脚本本身的文件

在我的 onetime.php 中,我的功能是 f711_my_onetime_function()。因为它可以是任何功能。我认为您的脚本已经过测试并且正常工作。

为了实现对脚本执行的控制,我使用两者

能力控制

阻止其他用户不小心执行我的脚本:

if ( current_user_can( 'manage_options' ) ) // check for administrator rights

要么

if ( get_current_user_id() == 711 ) // check if it is me - I prefer restricting the execution to me, not to all admins.

一瞬间

阻止自己不止一次地不经意地执行该脚本。

$transient = 'f711_my_onetime_check';
if ( !get_transient( $transient ) ) // check if the function was not executed.

在我的函数 f711_my_onetime_function()中执行脚本的文件将如下所示:

$transient = 'f711_my_onetime_check';
if ( get_current_user_id() == 711 && !get_transient( $transient ) ) {

    set_transient( $transient, 'locked', 600 ); // lock function for 10 Minutes
    add_action( 'wp_footer', 'f711_my_onetime_function' ); // execute my function on the desired hook.

}

function f711_my_onetime_function() {
    // all my glorious one-time-magic.
}

在检查之后立即设置瞬变的原因是否存在是我希望在脚本被锁定后被执行的功能被使用两次。

如果我需要我的功能的任何输出,我打印出来作为一个注释在页脚,或有时甚至过滤的内容。

锁定时间设置为 10 分钟,但可以根据您的需要进行调整。

Cleanup

成功执行我的脚本后,从 functions.php 中删除 include,并从服务器中删除 onetime.php 。当我使用暂时性的超时时,我不需要清理数据库,但当然你也可以在删除文件之后删除瞬态。

次佳解决方案

你也可以这样做:

运行 onetime.php 并在执行后重命名它。

if ( current_user_can( 'manage_options' ) ) {

    if( ! file_exists( '/path/to/onetime.php' ) )
      return;
    add_action( 'wp_footer', 'ravs_my_onetime_function' ); // execute my function on the desired hook.

}

function ravs_my_onetime_function() {

    // all my glorious one-time-magic.
    include( '/path/to/onetime.php' );

   // after all execution rename your file;
   rename( '/path/to/onetime.php', '/path/to/onetime-backup.php');
}

第三种解决方案

我为此创建了一个命令行 Phing 脚本,除了加载外部脚本以外,它没有什么特别之处。我通过 CLI 使用它的原因是因为:

  • 我不想让它加载错误 (需要键入一个命令)
  • 它是安全的,因为它可以在 Web 根目录下运行,换句话说,它可以影响 WP,但 WP 无法以任何方式到达脚本。
  • 它不会向 WP 或 DB 本身添加任何代码。

require('..path to ../wp-blog-header.php');
//bunch of WP globals
define('WP_USE_THEMES', false);
//custom code

所以你可以使用 Phing 或 PHP CLI,并在晚上睡觉。 WP-CLI 也是一个很好的选择,尽管我忘记了如果您可以在 Web 根目录下使用它。

既然这是一个流行的帖子,这里是一个脚本的例子:https://github.com/wycks/WordPhing(run.php)

第四种方案

运行 one-time 脚本的另一个很简单的方法就是通过一个 MU 插件来实现。

将代码放在您上传到 MU 插件文件夹 (默认为/wp-content/mu-plugins) 的一些 PHP 文件 (例如,one-time.php) 中,调整文件权限,运行插件 (即根据您选择的挂钩,您基本只需访问前端/后端),你都完成了。

这是一个样板:

/**
* Main (and only) class.
*/
class OneTimeScript {

    /**
     * Plugin function hook.
     *
     * @type    string
     */
    public static $hook = 'init';


    /**
     * Plugin function priority.
     *
     * @type    int
     */
    public static $priority = 0;


    /**
     * Run the one-time script.
     *
     * @hook    self::$hook
     * @return  void
     */
    public static function run() {
        // one-time action goes here...

        // clean up
        add_action('shutdown', array(__CLASS__, 'unlink'), PHP_INT_MAX);
    } // function run


    /**
     * Remove the file.
     *
     * @hook    shutdown
     * @return  void
     */
    public static function unlink() {
        unlink(__FILE__);
    } // function unlink

} // class OneTimeScript

add_action(OneTimeScript::$hook, array('OneTimeScript', 'run'), OneTimeScript::$priority);

没有评论和内容,它只是看起来像这样:

class OneTimeScript {
    public static $hook = 'init';
    public static $priority = 0;

    public static function run() {
        // one-time action goes here...
        add_action('shutdown', array(__CLASS__, 'unlink'), PHP_INT_MAX);
    } // function run

    public static function unlink() {
        unlink(__FILE__);
    } // function unlink
} // class OneTimeScript
add_action(OneTimeScript::$hook, array('OneTimeScript', 'run'), OneTimeScript::$priority);

第五种方案

有时候我使用一个挂钩插件去激活的函数。

见这里 Update Old Links To Pretty Permalinks Custom Post Type

一旦只有管理员可以激活插件,就有一个功能检查作为副作用。

一旦停用,就不需要删除文件,不会被 wordress 包含。成瘾如果你想再次运行,你可以。再次激活和停用。

有时候我用 @fischi 的回答中使用了瞬态的。例如。这里是 query to create woocommerce products from images 或这里 Delete/replace img tags in post content for auto published posts

两者的组合可以是另一种选择。

第六种方案

在理想的条件下,我将 ssh 进入服务器,并使用 wp-cli 自己执行该功能。

这通常是不可能的,但是,我倾向于设置 $ _GET 变量并将其挂接到’init’,例如:

add_action( 'init', function() {
    if( isset( $_GET['one_time'] ) && $_GET['one_time'] == 'an_unlikely_string' ) {
        do_the_one_time_thing();
    }
});

然后打

http://my_blog.com/?one_time=an_unlikely_string

并在完成时禁用钩子。

第七种方案

绝对可以,只需创建一次性代码作为插件。

add_action('admin_init', 'one_time_call');
function one_time_call()
{
    /* YOUR SCRIPTS */
    deactivate_plugins('onetime/index.php'); //deactivate current plugin
}

问题如何激活此插件,而不点击激活链接?

只需在 functions.php 中加入 activate_plugins('onetime/index.php');

或使用必须使用插件 http://codex.wordpress.org/Must_Use_Plugins

尝试使用不同的操作,当你想执行一次性插件,

  1. admin_init – 管理员初始化后
  2. init – wordpress init
  3. wp – 加载 wordpress 时

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。