问题

我们所有人都处在这样的情况下,这个站点上的许多问题都需要这样的解决方案。您要么必须更新数据库,自动插入大量数据,要么转换meta_keys或类似的方法。

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

但是这样做的话,我很想听听您对这个问题的个人解决方案,以及您为什么选择您的解决方案。

问题

您如何实现一个您的(正在运行的)WordPress安装中是否存在时间脚本?

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


插入数据的脚本不应再运行不止一次
需要大量资源的脚本不应在无法监视的时候运行
它们不应偶然运行

我问的原因

我有自己的见习方法,我将其发布在答案中。我不知道这是否是最好的解决方案,所以我想了解您的解决方案。另外,这是一个在其他问题中经常问到的问题,拥有一个收集想法的资源非常有用。

,希望向您学习:)

评论

如果这确实是一次性交易,那么我编写脚本,运行它,然后删除它。此后没有人不能再次运行它。像所有事物一样,代码瞬息万变。 ;)

我担心的是,每次碰巧都可能再次调用脚本。但我无数次地采用了您的方法;)

在插件的管理页面上运行它,始终对我有用。您可以在页面顶部添加身份验证检查,以确保在必要时使用身份验证。

但是您不是在谈论计划的一次执行,而是手动操作?

是的,我只是在谈论手动准时操作,例如迁移脚本等,而不是wp-cron计划的事件。

#1 楼

我自己使用以下组合:


一个专用于一次性脚本的文件
使用瞬态阻止脚本意外运行超过一次
使用功能管理或用户控制来确保脚本仅由我运行。

结构

我在包含文件夹onetime.php中使用了一个文件(inc),该文件包含在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.
}


我检查瞬态是否存在后立即设置瞬态的原因是,我希望函数在脚本被锁定后不被蜂鸣两次使用后才能执行。 br />
如果我需要函数的任何输出,我可以将其打印为页脚中的注释,有时甚至过滤内容。

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

清理

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

评论


我本来打算添加我的答案,但是在阅读完该答案顶部的清单之后,我将不再...我的方法几乎完全相同。因此+1-对此也有详细的想法。

–tfrommen
2014-2-5 20:58



#2 楼

您还可以执行以下操作:

运行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');
}


评论


这就是我们要做的;它几乎可以保证是万无一失的。

– Qix-蒙尼卡(MS)被盗
2015年1月6日在21:07



太好了,我不知道为什么这个主意没想到,谢谢:)

– Shahin
20-2-11在7:01

#3 楼

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


我不希望它被错误加载(需要键入命令)
它很安全,因为它可以在Web根目录之外运行,换句话说,它可以影响WP,但是WP无法以任何方式到达脚本。
它不会向WP或数据库本身添加任何代码。


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。 com / wycks / WordPhing(run.php)

评论


这看起来很简单,很安全。您还通过使用命令行涵盖了​​我的主要关切之一(我偶然执行了两次)。好主意!

– fischi
2014年2月6日在7:18

#4 楼

在理想条件下,我会使用服务器ssh进入服务器并自己执行该函数。

这通常是不可能的,因此我倾向于设置$ _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


并在完成后禁用钩子。

#5 楼

运行一次性脚本的另一种非常简单的方法是通过MU插件执行此操作。

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

这是一个样板:

/**
* 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);


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

#6 楼

有时,我使用了与插件停用相关的函数。

请参见此处将旧链接更新为漂亮的永久链接自定义帖子类型

一旦只有管理员可以激活插件,就会出现功能检查的副作用。

没有必要删除文件,一旦停用,它便不会包含在wordress中。
如果您想重新运行它,可以上瘾。再次激活和停用。

有时我会像@fischi答案中那样使用瞬态。例如。在此处查询以从图像创建woocommerce产品,或在此处删除/替换自动发布的帖子的帖子内容中的img标签。

可以将两者结合使用。

评论


这也是一个非常好的主意。如果它变得烦人,总是必须再次激活才能将其停用,那么您也可以将相同的功能与该插件的激活挂钩,对吗?

– fischi
2014年2月6日在7:20

是的,如果你想。但是,我认为两次单击并不是运行一次性脚本的巨大努力。任何其他涉及CLI命令或文件处理(重新命名,删除)的解决方案都需要更多的“工作”。此外,每次依赖钩子时,都依赖于全局变量,从而增加了与代码的安全性/可预测性有关的潜在问题。 @fischi

– gmazzap♦
2014年2月6日11:00



我认为两次单击也不算太多,只是想问一下:)

– fischi
2014年2月6日,12:44

#7 楼

绝对可以,只需将您的一次性代码创建为插件即可。

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


问题如何在不单击“激活”链接的情况下激活该插件?

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


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

尝试不同的操作,就像当您要执行一次性插件,


admin_init-管理员初始化后
init-wordpress初始化
wp-加载wordpress时


#8 楼

另一种方法是在工作完成后设置全局wp_option,并在每次执行init钩子时检查该选项。

function my_one_time_function() {
    // Exit if the work has already been done.
    if ( get_option( 'my_one_time_function', '0' ) == '1' ) {
        return;
    }

    /***** DO YOUR ONE TIME WORK *****/

    // Add or update the wp_option
    update_option( 'my_one_time_function', '1' );
}
add_action( 'init', 'my_one_time_function' );


自然地,您不需要永远拥有此代码(即使是从数据库中读取的代码也是如此),因此您可以在工作完成后删除该代码。
如果需要重新执行此操作,则可以手动将此选项值更改为0执行代码。

#9 楼

我的方法与此有所不同。我想将一次性脚本作为函数添加到主题的function.php中,并在特定的GET查询上运行它。

if ( isset($_GET['linkupdate']) ) {
    add_action('init', 'link_update', 10);
}
function link_update() {
  // One Time Script
   die;
}


要运行此脚本,只需访问网址“ www.sitename.com/?linkupdate”

到目前为止,这对我来说仍然很好...

这种方法是否有任何缺点?只是想知道...

#10 楼

我只使用了一个未使用的自定义产品模板页面,并且未连接到公共服务器上的任何内容。

如果我有一个不在使用中的推荐页面(在草稿模式下) (或其他),但连接到单个页面模板,例如single-testimonial.php-我可以在其中放置函数,通过preview加载页面,然后函数或任何函数启动一次。在调试的情况下对功能进行修改也非常容易。

确实很容易,并且我更喜欢使用init,因为我可以更好地控制其启动时间和方式。只是我的喜好。

#11 楼

以防万一,这就是我所做的并且效果很好:

add_action( 'init', 'upsubscriptions_setup');

function upsubscriptions_setup()
{
    $version = get_option('upsubscriptions_setup_version');

    // If no version is recorded yet in the DB
    if (!$version) {
        add_option('upsubscriptions_setup_version', '0.1');
        $version = get_option('upsubscriptions_setup_version');
    }

    if (version_compare($version, "0.1") <= 0) {
        // do stuff
        update_option('upsubscriptions_setup_version', '0.2');
    }

    if (version_compare($version, "0.2") <= 0) {
        // do stuff
        update_option('upsubscriptions_setup_version', '0.3');
    }

    if (version_compare($version, "0.3") <= 0) {
        // do stuff
        update_option('upsubscriptions_setup_version', '0.4');
    }

    // etc
}


#12 楼

使用wp-cli eval-file很棒。您甚至可以在具有本地脚本的远程系统(使用'@'ssh别名)上进行操作。
如果您在wordpress基本目录中的one-time.php中有您的代码,并且您想要的系统上有命令行可以执行以下操作:
wp eval-file one-time.php

如果本地具有文件one-time.php,并且您想使用@在远程wordpress上运行它,则如下所示:
wp @remote eval-file - < one-time.php