วิธีที่ดีที่สุดในการเรียกใช้งานสคริปต์ครั้งเดียวของคุณคืออะไร?


32

ปัญหา

เราทุกคนตกอยู่ในสถานการณ์เช่นนี้และคำถามมากมายในเว็บไซต์นี้ต้องการทางออกเช่นนี้ คุณต้องอัปเดตฐานข้อมูลแทรกข้อมูลจำนวนมากโดยอัตโนมัติแปลงmeta_keysหรือสิ่งที่คล้ายกัน

แน่นอนในระบบที่ใช้งานตามแนวปฏิบัติที่ดีที่สุดสิ่งนี้ไม่ควรเกิดขึ้น

แต่ถ้าเป็นเช่นนั้นฉันชอบที่จะได้ยินคำตอบส่วนตัวของคุณเกี่ยวกับปัญหานี้และทำไมคุณเลือกคุณ

คำถาม

คุณใช้สคริปต์แบบครั้งเดียวในการติดตั้ง WordPress ของคุณได้อย่างไร

ปัญหาที่นี่ส่วนใหญ่เป็นเพราะเหตุผลดังต่อไปนี้:

  • สคริปต์ที่แทรกข้อมูลไม่ควรรันมากกว่าหนึ่งครั้ง
  • สคริปต์ที่ต้องใช้ทรัพยากรจำนวนมากไม่ควรเรียกใช้ในเวลาที่ไม่สามารถตรวจสอบได้
  • ไม่ควรดำเนินการโดยไม่ตั้งใจ

เหตุผลที่ฉันถาม

ฉันได้รับการฝึกฝนของตัวเองฉันจะโพสต์ในคำตอบ อย่างที่ฉันไม่รู้ว่ามันเป็นทางออกที่ดีที่สุดหรือไม่ฉันต้องการทราบเกี่ยวกับคุณ นอกจากนี้คำถามนี้ถูกถามบ่อยครั้งในบริบทของคำถามอื่น ๆ และจะเป็นการดีหากมีแหล่งข้อมูลที่รวบรวมความคิด

รอคอยที่จะเรียนรู้จากคุณ :)


2
หากเป็นข้อตกลงเพียงครั้งเดียวอย่างแท้จริงจากนั้นฉันเขียนสคริปต์ฉันเรียกใช้แล้วฉันจะลบมัน ไม่มีใครสามารถเรียกใช้มันได้อีกหลังจากนั้น รหัสก็หายวับไปเหมือนทุกสิ่ง ;)
อ็อตโต

1
ฉันกังวลว่าสคริปต์อาจถูกเรียกอีกครั้งเป็นครั้งที่สองโดยบังเอิญ แต่ฉันทำตามวิธีของคุณนับครั้งไม่ถ้วน;)
fischi

เรียกใช้บนหน้าผู้ดูแลระบบของปลั๊กอินใช้งานได้สำหรับฉันเสมอ คุณสามารถเพิ่มการตรวจสอบความถูกต้องที่ด้านบนของหน้าเพื่อให้แน่ใจว่าเป็นของคุณถ้าจำเป็น
Andrew Bartel

แต่คุณไม่ได้พูดถึงการดำเนินการครั้งเดียวที่กำหนดไว้มีเพียงคู่มือเท่านั้น?
Birgire

1
ใช่ฉันกำลังพูดถึงการดำเนินการตามกำหนดเวลาด้วยตนเองเช่นการย้ายข้อมูลสคริปต์ ฯลฯ ไม่ใช่wp-cronเหตุการณ์ที่กำหนดไว้
fischi

คำตอบ:


17

ฉันเพื่อตัวเองใช้การรวมกันของ:

  • หนึ่งไฟล์ที่อุทิศให้กับสคริปต์ครั้งเดียว
  • ใช้ชั่วคราวเพื่อหยุดสคริปต์จากการทำงานมากกว่าหนึ่งครั้งโดยไม่ตั้งใจ
  • ใช้การจัดการความสามารถหรือการควบคุมผู้ใช้เพื่อให้แน่ใจว่าสคริปต์นั้นถูกเรียกใช้โดยฉัน

โครงสร้าง

ฉันใช้ไฟล์ ( onetime.php) ในโฟลเดอร์รวมของฉัน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.
}

เหตุผลที่ฉันตั้งค่า transient ทันทีหลังจากตรวจสอบหากมีอยู่นั่นคือฉันต้องการให้เรียกใช้ฟังก์ชันหลังจากสคริปต์ถูกล็อกจาก beeing ใช้สองครั้ง

หากฉันต้องการผลงานใด ๆ จากฟังก์ชั่นของฉันฉันจะพิมพ์มันออกมาเป็นความคิดเห็นในส่วนท้ายหรือบางครั้งฉันก็กรองเนื้อหา

lockouttime ตั้งไว้ที่ 10 นาที แต่สามารถปรับได้ตามความต้องการของคุณ

ทำความสะอาด

หลังจากการดำเนินการที่ประสบความสำเร็จของสคริปต์ของฉันฉันลบincludeจากfunctions.phpและลบออกonetime.phpจากเซิร์ฟเวอร์ ขณะที่ฉันใช้การหมดเวลาใช้งานชั่วคราวฉันไม่จำเป็นต้องทำความสะอาดฐานข้อมูล แต่แน่นอนว่าคุณสามารถลบชั่วคราวได้หลังจากที่คุณลบไฟล์


ฉันคิดถึงการเพิ่มคำตอบของฉันลงในรายการนี้ แต่หลังจากอ่านรายชื่อของคุณที่ด้านบนสุดของคำตอบนี้ ... ฉันจะไม่ทำอีกต่อไป ดังนั้น +1 สำหรับสิ่งนี้ - สำหรับความคิดโดยละเอียดเกี่ยวกับสิ่งนี้
tfrommen

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 นั้นเป็นเพราะ:

  • ฉันไม่ต้องการให้โหลดโดยไม่ตั้งใจ (จำเป็นต้องพิมพ์คำสั่ง)
  • มีความปลอดภัยเนื่องจากสามารถเรียกใช้ภายนอกรูทเว็บได้อีกนัยหนึ่งคือมันมีผลต่อ 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 ยังเป็นทางเลือกที่ดีแม้ว่าฉันจะลืมว่าคุณสามารถใช้งานได้นอกเว็บรูท

เนื่องจากนี่คือโพสต์ยอดนิยมที่นี่เป็นตัวอย่างของสคริปต์: https://github.com/wycks/WordPhing (run.php)


มันดูดีและเรียบง่ายและปลอดภัย คุณยังครอบคลุมหนึ่งในข้อกังวลหลักของฉัน (ฉันดำเนินการสองครั้งโดยไม่ตั้งใจ) เพื่อขยายค่อนข้างโดยใช้บรรทัดคำสั่ง ความคิดดี!
fischi

5

อีกวิธีที่ง่าย ๆ ในการเรียกใช้สคริปต์ครั้งเดียวคือการทำเช่นนี้โดยใช้ปลั๊กอิน MU

ใส่รหัสในไฟล์ PHP บางไฟล์ (เช่นone-time.php) ที่คุณอัปโหลดไปยังโฟลเดอร์ปลั๊กอิน MU ของคุณ (โดยค่าเริ่มต้น/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);

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 จากภาพหรือที่นี่ลบ / แทนที่แท็ก img ในเนื้อหาโพสต์สำหรับโพสต์ที่เผยแพร่อัตโนมัติ

การรวมกันของทั้งสองสามารถเป็นทางเลือก


นี่เป็นความคิดที่ดีจริงๆ หากเป็นเรื่องน่ารำคาญที่ต้องเปิดใช้งานเพื่อปิดการใช้งานอีกครั้งคุณสามารถขอฟังก์ชั่นเดียวกันกับการเปิดใช้งานปลั๊กอินได้ใช่ไหม
fischi

ได้ถ้าคุณต้องการ. อย่างไรก็ตามฉันคิดว่าการคลิก 2 ครั้งนั้นไม่ใช่ความพยายามที่ดีในการเรียกใช้สคริปต์ครั้งเดียว โซลูชันอื่นใดที่เกี่ยวข้องกับคำสั่ง CLI หรือการจัดการไฟล์ (เปลี่ยนชื่อลบ) ต้องมี "งาน" มากขึ้น นอกจากนี้ทุกครั้งที่คุณพึ่งพา hooks คุณจะต้องพึ่งพาตัวแปรทั่วโลกเพิ่มชั้นของปัญหาที่อาจเกิดขึ้นเกี่ยวกับความปลอดภัย / การคาดการณ์ของรหัส @fischi
gmazzap

ฉันไม่คิดว่าสองคลิกมากเกินไปทั้งเพียงแค่อยากจะถาม :)
fischi

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

หรือใช้ต้องใช้ปลั๊กอินhttp://codex.wordpress.org/Must_Use_Plugins

ลองด้วยการกระทำที่แตกต่างเช่นเมื่อคุณต้องการเรียกใช้งานปลั๊กอินเพียงครั้งเดียว

  1. admin_init - หลังจากผู้ดูแลระบบ init

  2. init - wordpress init

  3. wp - เมื่อโหลดเวิร์ดเพรส


2

อีกวิธีหนึ่งคือการตั้งค่า wp_option ทั่วโลกเมื่องานเสร็จสิ้นและตรวจสอบตัวเลือกนั้นทุกครั้งที่เริ่มใช้ hook hook

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- ฉันสามารถวางฟังก์ชั่นในนั้นโหลดหน้าเว็บผ่านทาง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.