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


32

問題

私たちは皆このような状況にあり、このサイトに関する多くの質問にはこのような解決策が必要です。データベースを更新するか、大量のデータを自動的に挿入するmeta_keysか、変換するか、または同様のものが必要です。

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

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

質問

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

ここでの問題は、主に次の理由によるものです。

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

私が尋ねる理由

私は自分の練習をしました。答えにそれを投稿します。それが最善の解決策であるかどうかはわかりませんので、あなたのことを知りたいです。また、これは他の質問の文脈で何度も尋ねられる質問であり、アイデアを収集するリソースを持っていることは素晴らしいことです。

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


2
本当に1回限りの場合は、スクリプトを作成し、実行してから削除します。その後誰もそれを再び実行することはできません。すべてのものと同様に、コードはつかの間です。;)
オットー14年

1
偶然、スクリプトが2度目に呼び出されるのではないかと心配しています。しかし、私はあなたのアプローチを何度も
やりました

プラグインの管理ページで実行し、常に私のために働いた。ページの上部に認証チェックを追加して、必要に応じて自分自身であることを確認できます。
アンドリューバーテル

しかし、あなたはスケジュールされた 1回の実行について話しているのではなく、手動ですか?
バージール14

1
はい、wp-cronスケジュールされたイベントではなく、移行スクリプトなどの手動のオンタイム操作についてのみ話します。
フィスキ14

回答:


17

私自身は、次の組み合わせを使用します。

  • ワンタイムスクリプト専用の1つのファイル
  • トランジェントを使用して、スクリプトが誤って複数回実行されるのを防ぎます
  • 機能管理またはユーザーコントロールを使用して、スクリプトが自分で実行されるようにします。

構造

onetime.phpinclude-folderでファイル()を使用します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.
}

チェックが存在するかどうかを確認した直後にトランジェントを設定したのは、スクリプトが2回使用されないようにロックされた後に関数を実行するためです。

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

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

掃除

スクリプトが正常に実行された後、includeからを削除し、サーバーからfunctions.php削除onetime.phpします。トランジェントにタイムアウトを使用したため、データベースをクリーンアップする必要はありませんが、もちろん、ファイルを削除した後にトランジェントを削除することもできます。


私はこれに答えを追加することを考えましたが、この答えの一番上にあるリスティングを読んだ後...私のアプローチはほとんどまったく同じに見えるので、私はもういません。このために+1-これについての詳細な考えも。
tfrommen 14

14

これも行うことができます:

実行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

7

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


これは見た目もシンプルで、安全です。また、コマンドラインを使用して、私の主な懸念(偶然2回実行すること)の1つを大幅に拡張しました。良いアイデア!
フィスキ14

5

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

one-time.phpMUプラグインのフォルダーにアップロードするPHPファイル(例:)にコードを配置し(デフォルトで/wp-content/mu-plugins)、ファイルのアクセス許可を調整し、プラグインを実行します(つまり、選択したフックに従って、基本的にフロントエンドにアクセスするだけです) / backend)、これですべて完了です。

決まり文句は次のとおりです。

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

4

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

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


4

時々、プラグインの無効化にフックされた関数を使用しました。

こちらから古いリンクをかなりパーマリンクのカスタム投稿タイプに更新

管理者のみがプラグインをアクティブにできるようになると、副作用として機能チェックが行われます。

非アクティブ化されたファイルを削除する必要はありません。wordressに含まれません。あなたがそれをもう一度実行したい場合は中毒であなたができます。再度アクティブ化および非アクティブ化します。

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

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


これも本当に良いアイデアです。再度アクティブ化するために常にアクティブ化する必要があるのが面倒な場合は、同じ機能をプラグインのアクティブ化にフックすることもできますよね?
フィスキ14

はいもしあなたが望むのならば。ただし、1回限りのスクリプトを実行するのに2回のクリックは大きな努力ではないと思います。CLIコマンドまたはファイル処理(名前の変更、削除)を含む他のソリューションには、さらに「作業」が必要です。さらに、フックに依存するたびに、グローバル変数に依存し、コードのセキュリティ/予測可能性に関する潜在的な問題の層を追加します。@fischi
gmazzap

2回のクリックも多すぎるとは思わない。ただ質問したかっただけだ。
fischi 14

3

プラグインとしてワンタイムコードを作成するだけです。

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

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

ワンタイムプラグインを実行する場合など、さまざまなアクションを試してください。

  1. admin_init-admin initの後

  2. init-ワードプレスの初期化

  3. wp-ワードプレスがロードされたとき


2

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


1

私のアプローチはこれについて少し異なります。テーマの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

使用していない単一のカスタム製品テンプレートページを使用しているだけで、公開サーバー上の何にも接続されていません。

たとえば、ライブではなく(ドラフトモードなどで)単一のページテンプレートに接続されている紹介ページがある場合single-testimonial.php-関数をそこに配置し、a previewを介してページを読み込み、関数または何でも一度起動しました。また、デバッグの場合、関数を簡単に変更できます。

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


0

それが役立つ場合に備えて、これは私がやったことであり、うまく機能します:

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
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.