問題描述

問題

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