Thực hành tốt nhất của bạn để thực hiện các kịch bản một lần là gì?


32

Vấn đề

Tất cả chúng ta đã ở trong một tình huống như thế này, và rất nhiều câu hỏi trên trang web này cần một giải pháp như thế này. Bạn có thể phải cập nhật cơ sở dữ liệu, tự động chèn nhiều dữ liệu, chuyển đổi meta_keyshoặc một cái gì đó tương tự.

Tất nhiên, trong một hệ thống chạy dựa trên các thực tiễn tốt nhất, điều này không nên xảy ra.

Nhưng như nó, tôi rất thích nghe giải pháp cá nhân của bạn cho vấn đề này, và tại sao bạn chọn giải pháp của bạn.

Câu hỏi

Làm thế nào để bạn thực hiện các tập lệnh một lần trong cài đặt WordPress (đang chạy) của bạn?

Vấn đề ở đây chủ yếu là vì những lý do sau:

  • Các tập lệnh chèn dữ liệu không nên chạy nhiều hơn một lần
  • Các tập lệnh yêu cầu nhiều nguồn tài nguyên không nên chạy vào thời điểm mà chúng không thể được giám sát
  • Họ không nên chạy một cách tình cờ

Lý do tôi hỏi

Tôi đã có thực hành của riêng tôi, tôi sẽ đăng nó trong câu trả lời. Vì tôi không biết đó có phải là giải pháp tốt nhất ngoài kia không, tôi muốn biết về bạn. Ngoài ra, đây là một câu hỏi được hỏi rất nhiều lần trong bối cảnh của các câu hỏi khác, và sẽ thật tuyệt khi có một nguồn tài nguyên thu thập các ý tưởng.

mong được học hỏi từ bạn :)


2
Nếu đó thực sự là giao dịch một lần duy nhất, thì tôi viết kịch bản, tôi chạy nó, sau đó tôi xóa nó. Không ai có thể chạy lại nó sau đó. Giống như tất cả mọi thứ, mã là thoáng qua. ;)
Otto

1
Điều tôi lo lắng là một kịch bản có thể được gọi lần thứ hai, mỗi lần trùng hợp. nhưng tôi đã làm cách tiếp cận của bạn vô số lần;)
fischi

Chạy nó trên trang quản trị của một plugin, luôn làm việc cho tôi. Bạn có thể thêm kiểm tra xác thực ở đầu trang để đảm bảo đó là bạn nếu cần thiết.
Andrew Bartel

nhưng bạn không nói về việc thực hiện một lần theo lịch trình , chỉ bằng tay ?
bạch dương

1
Vâng, tôi chỉ nói về các hoạt động đúng giờ thủ công, như di chuyển các tập lệnh, v.v., không phải wp-croncác sự kiện theo lịch trình.
fischi

Câu trả lời:


17

Tôi tự mình sử dụng kết hợp:

  • một tệp dành riêng cho tập lệnh một lần
  • sử dụng tạm thời để ngăn tập lệnh vô tình chạy nhiều lần
  • sử dụng quản lý khả năng hoặc kiểm soát người dùng để đảm bảo tập lệnh được điều hành bởi tôi.

Kết cấu

Tôi sử dụng một tệp ( onetime.php) trong thư mục bao gồm của mình inc, được bao gồm trong functions.phpvà được xóa từ đó sau khi sử dụng.

include( 'inc/onetime.php' );

Các tập tin cho chính kịch bản

Trong onetime.phpchức năng của tôi f711_my_onetime_function()được đặt. Vì nó có thể là bất kỳ chức năng. Tôi giả sử kịch bản của bạn được kiểm tra và hoạt động chính xác.

Để đạt được sự kiểm soát đối với việc thực thi tập lệnh, tôi sử dụng cả hai

Kiểm soát khả năng

Để ngăn người dùng khác vô tình thực thi tập lệnh của tôi:

if ( current_user_can( 'manage_options' ) ) // check for administrator rights

hoặc là

if ( get_current_user_id() == 711 ) // check if it is me - I prefer restricting the execution to me, not to all admins.

thoáng qua

để ngăn mình khỏi việc vô tình thực hiện kịch bản nhiều lần.

$transient = 'f711_my_onetime_check';
if ( !get_transient( $transient ) ) // check if the function was not executed.

Tệp để thực thi tập lệnh trong hàm của tôi f711_my_onetime_function()sẽ trông như thế:

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

Lý do tôi đặt tạm thời ngay sau khi kiểm tra nếu nó tồn tại là vì tôi muốn chức năng được thực thi sau khi tập lệnh đã bị khóa khỏi việc sử dụng hai lần.

Nếu tôi cần bất kỳ đầu ra nào từ chức năng của mình, tôi sẽ in nó ra dưới dạng một nhận xét ở chân trang hoặc đôi khi tôi thậm chí còn lọc nội dung.

Thời gian khóa được đặt thành 10 phút, nhưng có thể được điều chỉnh theo nhu cầu của bạn.

Dọn dẹp

Sau khi thực hiện thành công tập lệnh của tôi, tôi xóa includetừ functions.phpvà xóa onetime.phpkhỏi máy chủ. Khi tôi sử dụng thời gian chờ tạm thời, tôi không cần phải xóa cơ sở dữ liệu, nhưng tất nhiên bạn cũng có thể xóa tạm thời sau khi bạn xóa tệp.


Tôi đã nghĩ đến việc thêm câu trả lời của mình vào câu hỏi này, nhưng sau khi đọc danh sách của bạn ngay trên đầu câu trả lời này ... Tôi sẽ không nói nữa vì cách tiếp cận của tôi trông gần giống hệt nhau. Vì vậy, +1 cho điều này - cũng cho những suy nghĩ chi tiết về điều này.
tfrommen

14

Bạn cũng có thể làm điều này:

chạy onetime.phpvà đổi tên nó sau khi thực hiện.

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

Đây là những gì chúng ta làm; nó được đảm bảo khá nhiều để được chứng minh ngu ngốc.
Qix

7

Tôi đã tạo một tập lệnh Phing script cho việc này, nó không có gì đặc biệt ngoài việc tải một tập lệnh bên ngoài để chạy. Lý do tôi sử dụng nó thông qua CLI là vì:

  • Tôi không muốn nó tải nhầm (cần phải gõ lệnh)
  • Nó an toàn vì nó có thể được chạy bên ngoài web root, nói cách khác, nó có thể ảnh hưởng đến WP nhưng WP không thể tiếp cận tập lệnh theo bất kỳ cách nào.
  • Nó không thêm bất kỳ mã nào vào WP hoặc chính DB.

require('..path to ../wp-blog-header.php');
//bunch of WP globals
define('WP_USE_THEMES', false);
//custom code

Vì vậy, bạn có thể sử dụng Phing hoặc PHP CLI và ngủ vào ban đêm. WP-CLI cũng là một lựa chọn tốt mặc dù tôi quên nếu bạn có thể sử dụng nó bên ngoài web root.

Vì đây là một bài đăng phổ biến ở đây là một ví dụ về tập lệnh: https://github.com/wycks/WordP Breath (run.php)


Điều này trông đẹp và đơn giản, cũng như an toàn. Bạn cũng đề cập đến một trong những mối quan tâm chính của tôi (tôi thực hiện hai lần một cách tình cờ) đến một phần mở rộng bằng cách sử dụng dòng lệnh. Ý kiến ​​hay!
fischi

5

Một cách khá đơn giản khác để chạy tập lệnh một lần là thực hiện việc này bằng plugin MU.

Đặt mã trong một số tệp PHP (ví dụ one-time.php:) mà bạn tải lên thư mục trình cắm MU của bạn (theo mặc định /wp-content/mu-plugins), điều chỉnh quyền của tệp, chạy plugin (nghĩa là theo hook bạn đã chọn, về cơ bản bạn chỉ cần truy cập vào frontend / phụ trợ), và bạn đã hoàn tất.

Đây là một cái nồi:

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

Không có ý kiến ​​và công cụ, nó chỉ trông như thế này:

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

Trong điều kiện lý tưởng, tôi sẽ ssh vào máy chủ và tự thực hiện chức năng bằng wp-cli.

Tuy nhiên, điều này thường không thể thực hiện được, vì vậy tôi có xu hướng đặt biến $ _GET và móc nó vào 'init', ví dụ:

add_action( 'init', function() {
    if( isset( $_GET['one_time'] ) && $_GET['one_time'] == 'an_unlikely_string' ) {
        do_the_one_time_thing();
    }
});

sau đó đánh

http://my_blog.com/?one_time=an_unlikely_string

và vô hiệu hóa móc khi hoàn thành.


4

Đôi khi tôi đã sử dụng một chức năng được nối vào việc hủy kích hoạt plugin.

Xem ở đây Cập nhật các liên kết cũ để khá Permalinks Loại bài tùy chỉnh

Khi chỉ quản trị viên mới có thể kích hoạt bổ trợ, kiểm tra khả năng là tác dụng phụ.

Không cần phải xóa tệp sau khi tắt, nó sẽ không được bao gồm bởi wordress. Trong nghiện nếu bạn muốn chạy lại nó có thể. Kích hoạt và hủy kích hoạt lại.

Và đôi khi tôi đã sử dụng tạm thời được sử dụng như trong câu trả lời @fischi. Ví dụ: ở đây truy vấn để tạo các sản phẩm thương mại điện tử từ hình ảnh hoặc ở đây Xóa / thay thế thẻ img trong nội dung bài đăng cho các bài đăng được xuất bản tự động

Một sự kết hợp của cả hai có thể là một sự thay thế.


Đây cũng là một ý tưởng thực sự tốt. Nếu nó trở nên khó chịu khi luôn phải kích hoạt để hủy kích hoạt lại, bạn cũng có thể nối chức năng tương tự để kích hoạt plugin, phải không?
fischi

Có nếu bạn muốn. Tuy nhiên, tôi nghĩ rằng 2 lần nhấp không phải là một nỗ lực lớn để chạy tập lệnh một lần. Bất kỳ giải pháp nào khác liên quan đến lệnh CLI hoặc xử lý tệp (đổi tên, xóa) đều cần nhiều "công việc" hơn. Ngoài ra, mỗi khi bạn dựa vào hook, bạn đang dựa vào các biến toàn cục, thêm một lớp vấn đề tiềm ẩn liên quan đến bảo mật / dự đoán mã. @fischi
gmazzap

Tôi cũng không nghĩ rằng hai lần nhấp là quá nhiều, chỉ muốn hỏi :)
fischi

3

Chắc chắn bạn có thể, Chỉ cần tạo mã một lần của bạn dưới dạng plugin.

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

Vấn đề làm thế nào để tôi kích hoạt plugin này mà không cần nhấp vào Kích hoạt liên kết?

chỉ cần thêm activate_plugins('onetime/index.php');vàofunctions.php

hoặc Sử dụng phải sử dụng plugin, http://codex.wordpress.org/Must_Use_Plugins

Hãy thử với các hành động khác nhau như khi bạn muốn thực thi plugin một lần,

  1. admin_init - sau khi quản trị init

  2. init - initpress

  3. wp - khi tải wordpress


2

Một cách khác là đặt wp_option toàn cầu khi công việc được hoàn thành và kiểm tra tùy chọn đó mỗi khi hook hook được thực thi.

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' );

Đương nhiên, bạn không cần phải có mã này mãi mãi (ngay cả khi nó chỉ đơn giản là đọc từ cơ sở dữ liệu), vì vậy bạn có thể xóa mã khi công việc được hoàn thành. Ngoài ra, bạn có thể tự thay đổi giá trị tùy chọn này thành 0 nếu bạn cần thực hiện lại mã.


1

Cách tiếp cận của tôi là một chút khác nhau về điều này. Tôi muốn thêm tập lệnh một lần của mình dưới dạng một hàm trong hàm.php của chủ đề và chạy nó trên một truy vấn GET cụ thể.

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

Để chạy cái này, chỉ cần truy cập URL "www.sitename.com/?linkupdate"

Điều này đang làm việc tốt cho tôi cho đến bây giờ ...

Phương pháp này có bất kỳ nhược điểm? Chỉ tự hỏi ...


1

Tôi chỉ sử dụng một trang mẫu sản phẩm tùy chỉnh duy nhất mà tôi không sử dụng và không được kết nối với bất kỳ thứ gì trên máy chủ công cộng.

Giống như nếu tôi có một trang chứng thực không tồn tại (ở chế độ nháp hoặc bất cứ thứ gì), nhưng được kết nối với một mẫu trang duy nhất, chẳng hạn single-testimonial.php- tôi có thể đặt các chức năng trong đó, tải trang qua a previewvà chức năng hoặc bất cứ thứ gì ra mắt một lần. Cũng rất dễ dàng để sửa đổi chức năng trong trường hợp gỡ lỗi.

Thực sự dễ dàng và tôi thích sử dụng nó hơn initbởi vì tôi có nhiều quyền kiểm soát hơn khi nào và làm thế nào nó ra mắt. Chỉ là sở thích của tôi.


0

Chỉ trong trường hợp nó giúp, đây là những gì tôi đã làm và nó hoạt động tốt:

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
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.