web-dev-qa-db-ja.com

ワンタイムスクリプトを実行するためのベストプラクティスは何ですか?

問題

私たち全員がこのような状況にありました、そしてこのサイトに関する多くの質問はこのような解決策を必要とします。データベースを更新するか、大量のデータを自動的に挿入するか、meta_keysを変換するか、またはそれに類似したものを行わなければなりません。

もちろん、ベストプラクティスに基づく実行中のシステムでは、これは起こりません。

しかしそれがそうであるように、私はこの問題に対するあなたの個人的な解決策、そしてなぜあなたがあなたのものを選んだのかを聞いてみたいです。

質問

(実行中の)WordPressインストールにワンタイムスクリプトをどのように実装しますか?

ここでの問題は主に以下の理由によるものです。

  • データを挿入するスクリプトは複数回実行しないでください。
  • 多くのリソースを必要とするスクリプトは、監視できないときには実行しないでください。
  • 彼らは偶然に実行されるべきではありません

私が求める理由

私は私自身の練習をしました、私は答えにそれを掲示するつもりです。それがそこで最良の解決策であるかどうか私にはわからないので、私はあなたのものについて知りたいのです。また、これは他の質問との関連で何度も質問される質問であり、アイデアを集めるリソースを持つことは素晴らしいことです。

あなたから学ぶことを楽しみにしています:)

31
fischi

私は自分自身のために:

  • ワンタイムスクリプト専用の1つのファイル
  • 一時的にスクリプトを誤って2回以上実行しないようにする
  • 機能管理またはユーザー制御を使用して、スクリプトが確実に実行されるようにします。

構造

私は自分のインクルードフォルダ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.

トランジェント

誤ってスクリプトを2回以上実行しないようにします。

$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.
}

チェックの直後にトランジェントを設定したのは、その関数を実行させたいからです - - スクリプトが2回使用されないようにロックされています。

関数からの出力が必要な場合は、フッターのコメントとして出力するか、場合によってはコンテンツをフィルタ処理することもあります。

ロックアウト時間は10分に設定されていますが、必要に応じて調整できます。

掃除

私のスクリプトの実行が成功した後、私はfunctions.phpからincludeを削除し、そしてサーバーからonetime.phpを削除します。一時的にタイムアウトを使用したので、データベースをクリーンアップする必要はありませんが、もちろんファイルを削除した後に一時的に削除することもできます。

16
fischi

またこれをすることができます:

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');
}
13
Ravinder Kumar

このためのコマンドライン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)

7
Wyck

ワンタイムスクリプトを実行するもう1つの非常に簡単な方法は、MUプラグインを使用してこれを実行することです。

MUプラグインのフォルダ(デフォルトではone-time.php)にアップロードするPHPファイル(例:/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);

コメントやものがなければ、それはちょうどこのようになります:

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);
5
tfrommen

時々私はプラグインの無効化に夢中になる機能を使用しました。

こちらを参照してください かなり古いパーマリンクへの古いリンクを更新するカスタム投稿タイプ

管理者だけがプラグインを有効にできるようになると、副作用として機能チェックがあります。

無効化されたファイルを削除する必要はありません。wordressには含まれません。あなたが再びそれを実行したい場合は中毒でそれができます。再度有効化および無効化してください。

そして時々私は@fischiの答えのようにトランジェントを使いました。例えば。 here 画像からwoocommerce製品を作成するためのクエリ またはhere 自動公開された投稿の投稿コンテンツのimgタグを削除/置換

両方を組み合わせて使用​​することもできます。

4
gmazzap

間違いなくあなたはできる、ただプラグインとしてあなたのワンタイムコードを作成する。

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

問題リンクを有効にするをクリックせずにこのプラグインを有効にするにはどうすればよいですか?

functions.phpactivate_plugins('onetime/index.php');を追加するだけです

またはUseはプラグインを使用する必要があります、 http://codex.wordpress.org/Must_Use_Plugins

あなたがワンタイムプラグインを実行したいときのように異なるアクションで試してみてください、

  1. admin_init - admin initの後

  2. init - ワードプレスinit

  3. wp - ワードプレスが読み込まれたとき

3
Amit Sukapure

理想的な条件下では、私はサーバに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

完了したらフックを無効にします。

3
djb

もう1つの方法は、作業が完了したときにグローバルな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に変更することもできます。

2
Mauro Mascia

私は自分が使っていない単一のカスタム商品テンプレートページを使っているだけで、パブリックサーバー上の何にも接続されていません。

(ドラフトモードなどで)ライブではないが、単一のページテンプレートに接続された紹介ページがある場合のように - single-testimonial.php - そこに関数を置くことができます、previewを介してページをロードしますそして機能または何でも一度起動されます。デバッグの場合には、関数を修正することも非常に簡単です。

起動はいつどのように開始するかをより細かく制御できるので、本当に簡単で、initを使用するよりも優先します。私の好みです。

1
bbruman

私のアプローチはこれとは少し異なります。私は私のテーマのfunction.phpの関数として私のワンタイムスクリプトを追加し、それを特定のGETクエリで実行したいです。

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

これを実行するには、URL "www.sitename.com/?linkupdate"にアクセスしてください。

これは今まで私のためにうまく働いています...

この方法には欠点がありますか?ただ不思議...

1
Sid

万が一それが助けになる、これは私がしたことであり、それはうまく機能します:

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
}
0
Adam Moss