Bir kerelik komut dosyalarını çalıştırmak için en iyi uygulamanız nedir?


32

Sorun

Hepimiz böyle bir durumdaydık ve bu sitedeki birçok soru bunun gibi bir çözüme ihtiyaç duyuyor. Bir veritabanını güncellemeniz, otomatik olarak çok fazla veri eklemeniz, dönüştürmeniz meta_keysveya benzeri bir işlem yapmanız gerekir .

Tabii ki, en iyi uygulamalara dayalı çalışan bir sistemde bu olmamalıdır.

Ama olduğu gibi, bu soruna kişisel çözümünüzü ve neden sizinkini seçtiğinizi duymayı çok isterim.

Soru

Bir kerelik komut dosyalarını (çalışan) WordPress yüklemenize nasıl uygularsınız?

Buradaki sorun temel olarak aşağıdaki nedenlerden kaynaklanmaktadır:

  • Veri ekleyen komut dosyaları birden fazla çalıştırılmamalıdır
  • Çok sayıda kaynak gerektiren komut dosyaları, izlenemeyecekleri bir zamanda çalıştırılmamalıdır
  • Kazayla çalıştırılmamalılar

Sormamın nedeni

Kendi uygulamam var, cevapları yazıyorum. Dışarıdaki en iyi çözüm olup olmadığını bilmediğim için, sizinkini bilmek istiyorum. Ayrıca, bu, diğer sorular bağlamında birçok kez sorulan bir sorudur ve fikirleri toplayan bir kaynağa sahip olmak harika olurdu.

sizden öğrenmek için bekliyorum :)


2
Gerçekten tek seferlik sadece bir anlaşma olursa, senaryoyu yazıyorum, çalıştırıyorum, sonra siliyorum. Bundan sonra kimse tekrar koşamaz. Her şey gibi, kod da dalgalanıyor. ;)
Otto

1
Mesele şu ki, bir senaryonun rastlantısal olarak ikinci kez çağrılabileceğinden endişeliyim. ama yaklaşımını sayısız kere yaptım;)
fischi

Bir eklentinin yönetici sayfasında çalıştırın, her zaman benim için çalıştı. Gerekirse sizden emin olmak için sayfanın üstüne auth kontrolleri ekleyebilirsiniz.
Andrew Bartel,

ama bir seferlik idam planlanan hakkında konuşmuyor , sadece manuel ?
Birgire

1
Evet, wp-cronzamanlanmış etkinliklerden değil, yalnızca el ile yapılan zaman işlemlerinden (örneğin, geçiş komut dosyaları vb.) Söz ediyorum .
fischi

Yanıtlar:


17

Ben kendim için bir kombinasyonunu kullandım:

  • bir kerelik betiğe adanmış bir dosya
  • betiğin yanlışlıkla birden fazla kez çalışmasını durdurmak için bir geçici kullanma
  • Script sadece benim tarafımdan çalıştırılmasını sağlamak için yetenek yönetimi veya kullanıcı kontrolü kullanarak.

yapı

Bir dosyayı (kullanmak onetime.phpbenim dahil-klasöründe) incdahildir, functions.phpve kullanımdan sonra oradan silindi.

include( 'inc/onetime.php' );

Komut dosyasının kendisi için dosya

Benim içinde onetime.phpbenim işlevi f711_my_onetime_function()yerleştirilir. Herhangi bir fonksiyon olabileceği gibi. Komut dosyanızın test edildiğini ve doğru çalıştığını farz ediyorum.

Komut dosyasının yürütülmesi üzerinde kontrolü sağlamak için her ikisini de kullanırım

Yetenek kontrolü

Diğer kullanıcıların yanlışlıkla betiğimi yürütmesini engellemek için:

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

veya

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

geçici

yanlışlıkla betiği birden fazla kez çalıştırmaktan kendimi durdurmak için.

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

Benim fonksiyonumda betiği çalıştırmak için kullanılan dosya f711_my_onetime_function()şöyle görünür:

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

Kontrolün hemen ardından geçici durumu ayarlamamın nedeni , senaryonun iki kez kullanılan arı kovanından kilitlendikten sonra işlevin yürütülmesini istiyorum .

İşlevimden herhangi bir çıktıya ihtiyacım olursa, onu altbilgide yorum olarak yazdırırım veya bazen içeriği filtrelerim.

Kilitlenme süresi 10 dakika olarak ayarlanmıştır, ancak ihtiyaçlarınıza göre ayarlanabilir.

Temizlemek

Senaryomun başarılı şekilde yürütülmesinden sonra silen includegelen functions.phpve kaldırmak onetime.phpsunucudan. Geçici için zaman aşımı kullandığım için veritabanını temizlememe gerek yok, ancak tabii ki dosyayı kaldırdıktan sonra da geçici olarak silebilirsiniz.


Buna cevabımı eklemeyi düşündüm, ama bu cevabın en üstünde girişinizi okuduktan sonra ... yaklaşımım neredeyse tamamen aynı gözüktüğü için artık yapmıyorum. Yani bunun için +1 - bununla ilgili detaylı düşünceler için.
tfrommen

14

Bunu da yapabilirsiniz:

çalıştırdıktan onetime.phpsonra çalıştırın ve yeniden adlandırı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');
}

Bu bizim yaptığımız şey; aptal olması oldukça garantilidir.
Qix

7

Bunun için Phing betiği komut satırı oluşturdum, çalıştırmak için harici bir betiği yüklemek dışında özel bir şey değil. CLI aracılığıyla kullanmamın nedeni şuydu:

  • Yanlışlıkla yüklenmesini istemiyorum (bir komut yazmanız gerekir)
  • Web kökünün dışında çalıştırılabildiğinden güvenlidir, başka bir deyişle WP'yi etkileyebilir ancak WP komut dosyasına hiçbir şekilde erişemez.
  • WP'ye veya DB'ye herhangi bir kod eklemiyor.

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

Böylece Phing veya PHP CLI kullanabilirsiniz ve gece uyuyabilirsiniz. WP-CLI ayrıca iyi bir alternatiftir, ancak bunu web kökü dışında kullanıp kullanamayacağınızı unutuyorum.

Bu popüler yazı olduğundan, betiğin bir örneği: https://github.com/wycks/WordPhing (run.php)


Bu hem güvenli hem de güzel ve basit görünüyor. Ayrıca ana kaygılarımdan birini (beni kazayla iki kez icra ettim) komut satırını kullanarak oldukça uzadı. İyi fikir!
fischi

5

Tek seferlik bir betiği çalıştırmanın başka bir basit yolu da bunu MU eklentisi aracılığıyla yapmaktır.

Kodu one-time.php, MU eklentilerinizin klasörüne yüklediğiniz bazı PHP dosyalarına (örneğin ) yerleştirin (varsayılan olarak /wp-content/mu-plugins), dosya izinlerini ayarlayın, eklentiyi çalıştırın (yani, seçtiğiniz kancaya göre, temelde sadece ön ucu ziyaret etmeniz gerekir). / arka uç), ve hepiniz bitirdiniz.

İşte bir kazan:

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

Yorumlar ve şeyler olmadan, sadece şuna benziyor:

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

İdeal koşullar altında sunucuya ssh ve wp-cli kullanarak işlevi kendim yürütmek istiyorum.

Ancak bu genellikle mümkün değildir, bu yüzden bir $ _GET değişkeni belirleme ve onu 'init' üzerine bağlama eğilimindeyim, örneğin:

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

sonra vur

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

ve bittiğinde kancayı devre dışı bırakın.


4

Bazen, eklentinin devre dışı bırakılmasına bağlı bir fonksiyon kullandım.

Buraya Bakın Oldukça Kalıcı Bağlantılara Özel Bağlantı Türünü Güncelle

Sadece yöneticiler eklentileri aktif hale getirebildiklerinde yan etki olarak bir yetenek kontrolü vardır.

Devre dışı bırakıldığında dosyayı silmeye gerek yoktur, wordress'e dahil edilmez. Bağımlılıkta tekrar koşmak isterseniz yapabilirsiniz. Tekrar etkinleştirme ve devre dışı bırakma.

Bazen fischi cevaplarında olduğu gibi geçici olay kullandım. Örneğin , resimlerden woocommerce ürünleri oluşturmak için buradaki sorguyu veya buradaki otomatik yayınlanmış gönderiler için gönderi içeriğindeki img etiketlerini silin / değiştirin

Her ikisinin bir kombinasyonu bir alternatif olabilir.


Bu da gerçekten iyi bir fikir. Tekrar devre dışı bırakmak için her zaman etkinleştirmek zorunda kalmak can sıkıcı hale gelirse, aynı işlevi eklentinin etkinleştirilmesine de bağlayabilirsiniz, değil mi?
fischi

Evet isterseniz. Ancak, 2 tıklamanın bir kerelik bir komut dosyası çalıştırmak için iyi bir çaba olmadığını düşünüyorum. CLI komutunu veya dosya işlemeyi (yeniden adlandırma, silme) içeren diğer tüm çözümler daha fazla "çalışmaya" ihtiyaç duyar. Ayrıca, her kancaya güvendiğiniz zaman, kodun güvenliği / tahmin edilebilirliği ile ilgili ek bir potansiyel sorun katmanı ekleyerek küresel değişkenlere güveniyorsunuzdur. @fischi
gmazzap

İki tıklamanın da çok fazla olduğunu sanmıyorum, sadece sormak istedim :)
fischi

3

Kesinlikle yapabilirsiniz, Sadece bir seferlik kodunuzu bir eklenti olarak oluşturun.

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

Sorun, Etkinleştir bağlantısını tıklatmadan bu eklentiyi nasıl etkinleştiririm?

Sadece eklemek activate_plugins('onetime/index.php');içindefunctions.php

veya Kullanım eklentileri kullanmalı, http://codex.wordpress.org/Must_Use_Plugins

Bir seferde eklenti çalıştırmak istediğiniz gibi farklı eylemler deneyin

  1. admin_init - yönetici girişinden sonra

  2. init - wordpress init

  3. wp - wordpress yüklendiğinde


2

Başka bir yol, iş yapıldığında global bir wp_option ayarlamak ve init hook her çalıştırıldığında bu seçeneği kontrol etmektir.

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

Doğal olarak, bu kodu sonsuza kadar kullanmanıza gerek kalmaz (veritabanından basit bir okuma bile olsa), bu nedenle muhtemelen çalışma bittiğinde kodu kaldırabilirsiniz. Ayrıca, kodu tekrar uygulamanız gerekirse, bu seçenek değerini el ile 0 olarak değiştirebilirsiniz.


1

Benim yaklaşımım bu konuda biraz farklı. Bir kerelik betiğimi tememin function.php işlevine bir işlev olarak eklemeyi ve belirli bir GET sorgusunda çalıştırmayı seviyorum.

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

Bunu çalıştırmak için, yalnızca "www.sitename.com/?linkupdate" URL’sini ziyaret edin.

Şimdiye dek bu benim için iyi çalışıyor.

Bu yöntemin herhangi bir sakıncası var mı? Sadece merak ediyorum ...


1

Yalnızca kullanmadığım ve ortak sunucudaki hiçbir şeye bağlı olmayan tek bir özel ürün şablonu sayfası kullanıyorum.

Canlı olmayan bir taslak sayfa var (taslak modunda veya her neyse), ancak tek bir sayfa şablonuna bağlıysam, örneğin single-testimonial.php- Oraya işlevler yerleştirebilir, sayfayı a previewveya işlevi veya bir kez başlattı. Ayrıca hata ayıklama durumunda işlevde değişiklikler yapmak çok kolaydır.

Gerçekten kolay ve kullanmayı tercih ediyorum initçünkü ne zaman ve nasıl başlatıldığını daha fazla kontrol edebiliyorum. Sadece benim tercihim.


0

Sadece yardım etmesi durumunda, yaptığım şey buydu ve iyi çalışıyor:

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
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.