it-swarm.com.de

Was ist Ihre bewährte Methode zum Ausführen von einmaligen Skripten?

Das Problem

Wir waren alle in einer solchen Situation und viele Fragen auf dieser Website erfordern eine solche Lösung. Sie müssen entweder eine Datenbank aktualisieren, viele Daten automatisch einfügen, meta_keys konvertieren oder ähnliches.

In einem laufenden System, das auf Best Practices basiert, sollte dies natürlich nicht passieren.

Aber ich würde gerne Ihre persönliche Lösung für dieses Problem erfahren und wissen, warum Sie sich für Ihre entschieden haben.

Die Frage

Wie implementieren Sie einmalige Skripte in Ihre (laufende) WordPress-Installation?

Das Problem ist hauptsächlich auf die folgenden Gründe zurückzuführen:

  • Skripte, die Daten einfügen, sollten nicht mehrmals ausgeführt werden
  • Skripts, die viele Ressourcen erfordern, sollten nicht zu einem Zeitpunkt ausgeführt werden, an dem sie nicht überwacht werden können
  • Sie sollten nicht versehentlich ausgeführt werden

Den Grund frage ich

Ich habe meine eigene Praxis, ich werde sie in den Antworten veröffentlichen. Da ich nicht weiß, ob es die beste Lösung ist, würde ich gerne etwas über Ihre wissen. Dies ist auch eine Frage, die häufig im Zusammenhang mit anderen Fragen gestellt wird, und es wäre großartig, wenn eine Ressource die Ideen sammelt.

Ich freue mich darauf, von dir zu lernen :)

31
fischi

Ich benutze für mich eine Kombination aus:

  • eine Datei für das einmalige Skript
  • verwenden eines Transienten, um zu verhindern, dass das Skript versehentlich mehr als einmal ausgeführt wird
  • verwenden des Capability-Managements oder der Benutzerkontrolle, um sicherzustellen, dass das Skript nur von mir ausgeführt wird.

Struktur

Ich verwende eine Datei (onetime.php) in meinem Include-Ordner inc, die im functions.php enthalten ist und von dort nach der Verwendung gelöscht wird.

include( 'inc/onetime.php' );

Die Datei für das Skript selbst

In meinem onetime.php ist meine Funktion f711_my_onetime_function() platziert. Da könnte es jede Funktion sein. Ich gehe davon aus, dass Ihr Skript getestet wurde und ordnungsgemäß funktioniert.

Um die Kontrolle über die Ausführung des Skripts zu erlangen, verwende ich beide

Fähigkeitskontrolle

So verhindern Sie, dass andere Benutzer versehentlich mein Skript ausführen:

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

oder

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

eine vorübergehende

um mich davon abzuhalten, das Skript versehentlich mehr als einmal auszuführen.

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

Die Datei zum Ausführen des Skripts in meiner Funktion f711_my_onetime_function() würde folgendermaßen aussehen:

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

Der Grund, warum ich den Transienten unmittelbar nach der Prüfung auf Vorhandensein gesetzt habe, ist, dass die Funktion ausgeführt werden soll nachdem das Skript für die zweimalige Verwendung gesperrt wurde.

Wenn ich eine Ausgabe von meiner Funktion benötige, drucke ich sie entweder als Kommentar in der Fußzeile aus oder filtere manchmal sogar den Inhalt.

Die Sperrzeit ist auf 10 Minuten eingestellt, kann aber an Ihre Bedürfnisse angepasst werden.

Aufräumen

Nach der erfolgreichen Ausführung meines Skripts lösche ich die include aus dem functions.php und entferne den onetime.php vom Server. Da ich für den Übergang eine Zeitüberschreitung verwendet habe, muss die Datenbank nicht bereinigt werden. Natürlich können Sie den Übergang auch löschen, nachdem Sie die Datei entfernt haben.

16
fischi

Sie können dies auch tun:

führen Sie onetime.php aus und benennen Sie ihn nach der Ausführung um.

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

Ich habe ein Befehlszeilen-Phing-Skript dafür erstellt. Es ist nichts Besonderes, als ein externes Skript zu laden, das ausgeführt werden soll. Der Grund, warum ich es über die CLI verwendet habe, ist folgender:

  • Ich möchte nicht, dass es versehentlich geladen wird (ich muss einen Befehl eingeben)
  • Es ist sicher, da es außerhalb des Webroot ausgeführt werden kann, mit anderen Worten, es kann WP bewirken, aber WP kann das Skript in keiner Weise erreichen.
  • Es wird kein Code zu WP oder der Datenbank selbst hinzugefügt.

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

Sie können also Phing oder die PHP CLI verwenden und nachts schlafen. Die WP-CLI ist auch eine gute Alternative, obwohl ich vergesse, ob Sie sie außerhalb des Webroot verwenden können.

Da dies ein beliebter Beitrag ist, ist hier ein Beispiel für das Skript: https://github.com/wycks/WordPhing (run.php)

7
Wyck

Eine andere ziemlich einfache Möglichkeit, ein einmaliges Skript auszuführen, ist die Verwendung eines MU-Plugins.

Fügen Sie den Code in eine PHP -Datei ein (z. B. one-time.php), die Sie in den Ordner Ihres MU-Plugins hochladen (standardmäßig /wp-content/mu-plugins), passen Sie die Dateiberechtigungen an und führen Sie das Plugin aus (z. B. entsprechend dem ausgewählten Hook). Sie müssen im Grunde nur das Frontend/Backend besuchen, und schon sind Sie fertig.

Hier ist ein Kesselschild:

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

Ohne die Kommentare und das Zeug sieht es einfach so aus:

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

Manchmal habe ich eine Funktion verwendet, die bei der Deaktivierung des Plugins aktiviert ist.

Sehen Sie hier Aktualisieren Sie alte Links auf hübsche Permalinks Benutzerdefinierter Beitragstyp

Sobald nur noch Administratoren Plugins aktivieren können, gibt es als Nebeneffekt einen Capability Check.

Es ist nicht nötig, die Datei zu löschen, wenn sie deaktiviert ist. Sie wird nicht von wordress aufgenommen. In der Sucht, wenn Sie es wieder ausführen möchten, können Sie. Aktivieren und wieder deaktivieren.

Und manchmal habe ich transient verwendet wie in @fischi answer. Z.B. hier Abfrage zum Erstellen von Woocommerce-Produkten aus Bildern oder hier Löschen/Ersetzen von img-Tags im Post-Inhalt für automatisch veröffentlichte Posts

Eine Kombination von beiden kann eine Alternative sein.

4
gmazzap

Auf jeden Fall können Sie, erstellen Sie einfach Ihren einmaligen Zeitcode als Plugin.

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

Problem, wie kann ich dieses Plugin aktivieren, ohne auf den Link Aktivieren zu klicken?

füge einfach activate_plugins('onetime/index.php'); in functions.php hinzu

oder Verwendung muss Plugins verwenden, http://codex.wordpress.org/Must_Use_Plugins

Versuchen Sie es mit verschiedenen Aktionen, als wenn Sie einmaliges Plugin ausführen möchten,

  1. admin_init - nach admin init

  2. init - WordPress Init

  3. wp - wenn WordPress geladen

3
Amit Sukapure

Unter idealen Bedingungen würde ich in den Server ssh und die Funktion selbst mit wp-cli ausführen.

Dies ist jedoch oft nicht möglich. Daher setze ich normalerweise eine $ _GET-Variable und hänge sie an 'init' an, zum Beispiel:

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

dann schlagen

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

und deaktivieren Sie den Haken, wenn es fertig ist.

3
djb

Eine andere Möglichkeit besteht darin, eine globale wp_option festzulegen, wenn die Arbeit abgeschlossen ist, und diese Option bei jeder Ausführung des init-Hooks zu überprüfen.

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

Natürlich müssen Sie diesen Code nicht für immer haben (auch wenn es sich um ein einfaches Lesen aus der Datenbank handelt), sodass Sie den Code wahrscheinlich entfernen können, wenn die Arbeit erledigt ist. Sie können diesen Optionswert auch manuell in 0 ändern, wenn Sie den Code erneut ausführen müssen.

2
Mauro Mascia

Ich verwende nur eine einzelne benutzerdefinierte Produktvorlagenseite, die ich nicht verwende und die mit nichts auf dem öffentlichen Server verbunden ist.

Zum Beispiel, wenn ich eine Testimonial-Seite habe, die nicht online ist (im Entwurfsmodus oder was auch immer), aber mit einer einzelnen Seitenvorlage verbunden ist, zum Beispiel single-testimonial.php - Ich kann Funktionen dort platzieren, die Seite über eine preview und die Funktion oder laden was auch immer einmal gestartet wird. Es ist auch sehr einfach, die Funktion beim Debuggen zu ändern.

Ist wirklich einfach und ich bevorzuge es, init zu verwenden, weil ich mehr Kontrolle darüber habe, wann und wie es gestartet wird. Nur meine Präferenz.

1
bbruman

Mein Ansatz ist diesbezüglich etwas anders. Ich füge mein einmaliges Skript gerne als Funktion in die function.php meines Themas ein und führe es auf einer bestimmten GET-Abfrage aus.

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

Um dies auszuführen, besuchen Sie einfach die URL "www.sitename.com/?linkupdate"

Das funktioniert bis jetzt gut für mich ...

Hat diese Methode irgendwelche Nachteile? Ich frage mich nur ...

1
Sid

Nur für den Fall, dass es hilft, habe ich das getan und es funktioniert gut:

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