Quelle est votre pratique habituelle pour exécuter des scripts uniques?

31

Le problème

Nous sommes tous dans une situation de ce type et de nombreuses questions sur ce site nécessitent une solution de ce type. Vous devez soit mettre à jour une base de données, insérer automatiquement beaucoup de données, convertir meta_keys ou quelque chose de similaire.

Évidemment, cela ne devrait pas arriver dans un système en fonctionnement basé sur les meilleures pratiques.

Mais dans ce cas, j'aimerais connaître votre solution personnelle à ce problème et la raison pour laquelle vous avez choisi la vôtre.

La question

Comment implémentez-vous des scripts uniques dans votre installation (en cours d'exécution) de WordPress?

Le problème ici est principalement dû aux raisons suivantes:

  • Les scripts qui insèrent des données ne doivent pas s'exécuter plus d'une fois
  • Les scripts nécessitant beaucoup de ressources ne doivent pas être exécutés à un moment où ils ne peuvent pas être surveillés
  • Ils ne doivent pas être exécutés par accident

La raison pour laquelle je pose la question

J'ai ma propre pratique, je vais l'afficher dans les réponses. Comme je ne sais pas si c'est la meilleure solution, j'aimerais connaître la vôtre. De plus, c’est une question fréquemment posée dans le contexte d’autres questions, et il serait bon de disposer d’une ressource rassemblant les idées.

dans l'espoir d'apprendre de vous:)

    
posée fischi 29.01.2014 - 17:24

11 réponses

15

Pour ma part, j'utilise une combinaison de:

  • un fichier dédié au script ponctuel
  • utilisant un transitoire pour empêcher le script de s'exécuter accidentellement plus d'une fois
  • en utilisant la gestion des capacités ou le contrôle de l'utilisateur pour vous assurer que le script est simplement exécuté par moi.

Structure

J'utilise un fichier ( onetime.php ) dans mon dossier-inclus inc , qui est inclus dans le functions.php et est supprimé de là après utilisation.

include( 'inc/onetime.php' );

Le fichier du script lui-même

Dans mon onetime.php ma fonction f711_my_onetime_function() est placée. Comme cela pourrait être n'importe quelle fonction. Je suppose que votre script est testé et fonctionne correctement.

Pour contrôler l'exécution du script, j'utilise les deux

.

Contrôle de capacité

Pour empêcher d'autres utilisateurs d'exécuter mon script par inadvertance:

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

ou

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

un transitoire

pour m'empêcher d'exécuter accidentellement le script plusieurs fois.

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

Le fichier d'exécution du script dans ma fonction f711_my_onetime_function() ressemblerait à ceci:

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

La raison pour laquelle j'ai défini le transitoire immédiatement après la vérification, si elle existe, est que je souhaite que la fonction soit exécutée après que le script ait été bloqué et utilisé deux fois.

Si j’ai besoin d’une sortie de ma fonction, je l’imprime sous forme de commentaire dans le pied de page ou, parfois, je filtre le contenu.

Le temps de verrouillage est défini sur 10 minutes, mais peut être adapté à vos besoins.

Nettoyage

Après l'exécution réussie de mon script, je supprime le include du functions.php et supprime le onetime.php du serveur. Comme j'ai utilisé un délai d'attente pour le transitoire, je n'ai pas besoin de nettoyer la base de données, mais vous pouvez bien sûr également supprimer le transitoire après avoir supprimé le fichier.

    
réponse donnée fischi 29.01.2014 - 17:24
12

Vous pouvez également faire ceci:

exécutez onetime.php et renommez-le après exécution.

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');
}
    
réponse donnée Ravinder Kumar 05.02.2014 - 20:58
7

J'ai créé un script Phing en ligne de commande pour cela, ce n'est rien de spécial si ce n'est de charger un script externe à exécuter. La raison pour laquelle je l'ai utilisé via la CLI est que:

  • Je ne veux pas le charger par erreur (il faut taper une commande)
  • Il est sécurisé car il peut être exécuté en dehors de la racine Web. En d'autres termes, il peut affecter WP, mais WP ne peut pas accéder au script de quelque manière que ce soit.
  • Cela n'ajoute aucun code à WP ou à la base de données elle-même.
require('..path to ../wp-blog-header.php');
//bunch of WP globals
define('WP_USE_THEMES', false);
//custom code

Vous pouvez donc utiliser Phing ou la CLI de PHP et dormir la nuit. Le WP-CLI est également une bonne alternative, même si j’oublie que vous pouvez l’utiliser en dehors de la racine Web.

Étant donné qu'il s'agit d'un article populaire, voici un exemple de script: enlace (run.php)

    
réponse donnée Wyck 06.02.2014 - 03:54
5

Un autre moyen assez simple d'exécuter un script unique consiste à le faire au moyen d'un plug-in MU.

Placez le code dans un fichier PHP (par exemple, one-time.php ) que vous téléchargez dans le dossier de vos plugins MU (par défaut, /wp-content/mu-plugins ), ajustez les droits d'accès au fichier, exécutez le plugin (c.-à-d. selon le hook choisi , il vous suffit simplement de visiter le frontend / backend), et vous avez terminé.

Voici un passe-partout:

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

Sans les commentaires et le reste, cela ressemble à ceci:

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);
    
réponse donnée tfrommen 05.02.2014 - 23:01
4

Parfois, j'ai utilisé une fonction accrochée à la désactivation du plugin.

Voir ici Mettre à jour les anciens liens Vers de jolis liens permanents Type de message personnalisé

Une fois que seuls les administrateurs peuvent activer les plugins, un contrôle de capacité est un effet secondaire.

Il n'est pas nécessaire de supprimer le fichier une fois désactivé, il ne sera pas inclus par mot. En dépendance, si vous voulez le courir à nouveau, vous le pouvez. Activer et désactiver à nouveau.

Et parfois j’utilisais des transitoires comme dans @fischi answer. Par exemple. Voici la requête pour créer des produits woocommerce à partir d'images . ou ici Supprimer / remplacer les balises img dans le contenu des publications pour les publications publiées automatiquement

Une combinaison des deux peut constituer une alternative.

    
réponse donnée gmazzap 05.02.2014 - 21:14
3

Dans des conditions idéales, j’ai ssh sur le serveur et exécuté moi-même la fonction avec wp-cli.

Cela n’est souvent pas possible, alors j’ai tendance à définir une variable $ _GET et à l’accrocher à 'init', par exemple:

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

puis appuyez sur

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

et désactivez le hook quand c'est fait.

    
réponse donnée djb 05.02.2014 - 20:38
3

Vous pouvez le faire, créez simplement votre code temporel unique en tant que plug-in.

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

Problème, comment puis-je activer ce plugin sans cliquer sur Activer le lien?

ajoutez simplement activate_plugins('onetime/index.php'); à functions.php

ou Utiliser doit utiliser des plugins, enlace

Essayez avec différentes actions comme lorsque vous voulez exécuter le plugin onetime,

  1. admin_init - après l'initiation de l'administrateur

  2. init - init Wordpress

  3. wp - lorsque WordPress est chargé

réponse donnée Amit Sukapure 08.02.2014 - 17:28
2

Une autre méthode consiste à définir une option globale wp_option lorsque le travail est terminé et à rechercher cette option à chaque exécution du hook 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' );

Naturellement, vous n'avez pas toujours besoin de ce code (même s'il s'agit d'une simple lecture de la base de données), vous pouvez donc probablement le supprimer une fois le travail terminé. Vous pouvez également modifier manuellement la valeur de cette option sur 0 si vous devez ré-exécuter le code.

    
réponse donnée Mauro Mascia 29.12.2014 - 12:22
1

Mon approche est un peu différente à ce sujet. J'aime ajouter mon script unique en tant que fonction dans le fichier function.php de mon thème et l'exécuter sur une requête GET spécifique.

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

Pour l'exécuter, il suffit de visiter l'URL "www.sitename.com/?linkupdate"

Cela fonctionne très bien pour moi jusqu'à maintenant ...

Cette méthode présente-t-elle des inconvénients? Je me demandais juste ...

    
réponse donnée Sid 16.06.2017 - 08:10
1

Je viens d'utiliser une seule page de modèle de produit personnalisé que je n'utilise pas et que je ne connecte à rien sur le serveur public.

Par exemple, si j'ai une page de témoignage qui n'est pas affichée (en mode brouillon ou autre), mais connectée à un seul modèle de page, par exemple single-testimonial.php - je peux y placer des fonctions, chargez la page via un preview et la fonction ou quoi que ce soit est lancé une fois. Il est également très facile de modifier la fonction en cas de débogage.

C'est vraiment facile et je préfère utiliser init parce que je contrôle plus quand et comment il est lancé. Juste ma préférence.

    
réponse donnée bbruman 09.07.2017 - 00:13
0

Au cas où cela aiderait, c’est ce que j’ai fait et cela fonctionne bien:

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
}
    
réponse donnée Adam Moss 19.11.2018 - 16:25

Lire d'autres questions sur les étiquettes