問題描述

問題

我們都在這樣的情況下,這個網站上的很多問題都需要這樣的解決方案。您必須更新數據庫,自動插入大量數據,轉換 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 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。