¿Cuál es su mejor práctica para ejecutar scripts únicos?

31

El problema

Todos hemos estado en una situación como esta, y muchas preguntas en este sitio necesitan una solución como esta. O tienes que actualizar una base de datos, insertar una gran cantidad de datos automáticamente, convertir meta_keys , o algo similar.

Por supuesto, en un sistema en ejecución basado en las mejores prácticas esto no debería ocurrir.

Pero a medida que lo haga, me encantaría escuchar su solución personal a este problema y por qué eligió la suya.

La pregunta

¿Cómo implementas scripts de un solo uso en tu instalación de WordPress (en ejecución)?

El problema aquí se debe principalmente a los siguientes motivos:

  • Los scripts que insertan datos no deben ejecutarse más de una vez
  • Los scripts que requieren una gran cantidad de recursos no deben ejecutarse en un momento en que no puedan ser monitoreados
  • No deben ejecutarse por accidente

La razón que pregunto

Tengo mi propia práctica, la voy a publicar en las respuestas. Como no sé si es la mejor solución que existe, me gustaría saber sobre la tuya. Además, esta es una pregunta que se hace muchas veces en el contexto de otras preguntas, y sería genial tener un recurso que recopile las ideas.

esperando aprender de ti :)

    
pregunta fischi 29.01.2014 - 17:24

11 respuestas

15

Yo uso una combinación de:

  • un archivo dedicado al script de una sola vez
  • usar un transitorio para evitar que el script se ejecute accidentalmente más de una vez
  • usar la administración de capacidades o el control de usuarios para garantizar que el script sea ejecutado por mí.

Estructura

Utilizo un archivo ( onetime.php ) en mi carpeta de inclusión inc , que se incluye en el functions.php y se elimina de allí después del uso.

include( 'inc/onetime.php' );

El archivo para el script en sí mismo

En mi onetime.php se coloca mi función f711_my_onetime_function() . Como podría ser cualquier función. Supongo que su script está probado y funciona correctamente.

Para lograr el control sobre la ejecución del script, uso los dos

Control de capacidad

Para evitar que otros usuarios ejecuten accidentalmente mi script:

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

o

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

un transitorio

para evitar la ejecución accidental del script más de una vez.

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

El archivo para ejecutar el script en mi función f711_my_onetime_function() se vería así:

$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 razón por la que configuro el transitorio inmediatamente después de la verificación, si existe, es porque quiero que la función se ejecute después de que el script se haya bloqueado y no se use dos veces.

Si necesito algún resultado de mi función, lo imprimo como un comentario en el pie de página, o incluso a veces filtro el contenido.

El tiempo de bloqueo se establece en 10 minutos, pero puede ajustarse a sus necesidades.

Limpieza

Después de la ejecución exitosa de mi script, elimino el include del functions.php y elimino el onetime.php del servidor. Como utilicé un tiempo de espera para el transitorio, no necesito limpiar la base de datos, pero, por supuesto, también podría eliminar el transitorio después de eliminar el archivo.

    
respondido por el fischi 29.01.2014 - 17:24
12

También puedes hacer esto:

ejecuta onetime.php y cambia su nombre después de la ejecució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');
}
    
respondido por el Ravinder Kumar 05.02.2014 - 20:58
7

Creé una secuencia de comandos de Phing de línea de comandos para esto, no es nada especial más que cargar una secuencia de comandos externa para ejecutar. La razón por la que lo usé a través del CLI es porque:

  • No quiero que se cargue por error (es necesario escribir un comando)
  • Es seguro ya que puede ejecutarse fuera de la raíz web, en otras palabras, puede afectar a WP, pero WP no puede acceder al script de ninguna manera.
  • No agrega ningún código a WP ni a la base de datos en sí.
require('..path to ../wp-blog-header.php');
//bunch of WP globals
define('WP_USE_THEMES', false);
//custom code

Para que pueda usar Phing o PHP CLI y dormir por la noche. El WP-CLI también es una buena alternativa, aunque olvido si puede usarlo fuera de la raíz web.

Dado que esta es una publicación popular, aquí hay un ejemplo del script: enlace (run.php)

    
respondido por el Wyck 06.02.2014 - 03:54
5

Otra forma bastante simple de ejecutar un script de una sola vez es hacerlo mediante un complemento MU.

Coloque el código en algún archivo PHP (por ejemplo, one-time.php ) que haya cargado en la carpeta de sus complementos MU (por defecto, /wp-content/mu-plugins ), ajuste los permisos de archivo, ejecute el complemento (es decir, de acuerdo con el gancho elegido) , básicamente solo tienes que visitar el frontend / backend), y listo.

Aquí hay una plantilla:

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

Sin los comentarios y esas cosas, se ve así:

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);
    
respondido por el tfrommen 05.02.2014 - 23:01
4

Algunas veces usé una función enganchada en la desactivación del complemento.

Consulte aquí Actualizar enlaces antiguos A Pretty Permalinks Tipo de publicación personalizada

Una vez que solo los administradores pueden activar los complementos, hay una verificación de capacidad como efecto secundario.

No es necesario eliminar el archivo una vez desactivado, Wordress no lo incluirá. En la adicción si quieres volver a correr lo puedes. Activando y desactivando de nuevo.

Y a veces utilicé transitorios utilizados como en @fischi answer. P.ej. Aquí consulta para crear productos de woocommerce a partir de imágenes o aquí Delete / Reemplace las etiquetas img en el contenido de las publicaciones publicadas automáticamente

Una combinación de ambos puede ser una alternativa.

    
respondido por el gmazzap 05.02.2014 - 21:14
3

En condiciones ideales, debería ingresar al servidor y ejecutar la función yo mismo usando wp-cli.

Sin embargo, esto a menudo no es posible, por lo que tiendo a establecer una variable $ _GET y la engancho en 'init', por ejemplo:

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

luego pulsa

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

y deshabilite el enlace cuando esté hecho.

    
respondido por el djb 05.02.2014 - 20:38
3

Definitivamente puedes, solo crea tu código de un solo uso como complemento.

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

Problema, ¿cómo activo este complemento sin hacer clic en Activar enlace?

simplemente agrega activate_plugins('onetime/index.php'); en functions.php

o El uso debe usar complementos, enlace

Intente con diferentes acciones como cuando desea ejecutar el complemento de una sola vez,

  1. admin_init - después de que el administrador inicie

  2. init - wordpress init

  3. wp - cuando se carga wordpress

respondido por el Amit Sukapure 08.02.2014 - 17:28
2

Otra forma es establecer una opción global wp_option cuando se realiza el trabajo y comprobar esa opción cada vez que se ejecuta el gancho de inicio.

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

Naturalmente, no necesita tener este código para siempre (incluso si se trata de una simple lectura de la base de datos), por lo que probablemente pueda eliminar el código cuando finalice el trabajo. También puede cambiar manualmente el valor de esta opción a 0 si necesita volver a ejecutar el código.

    
respondido por el Mauro Mascia 29.12.2014 - 12:22
1

Mi enfoque es un poco diferente en esto. Me gusta agregar mi script de una sola vez como una función en function.php de mi tema y ejecutarlo en una consulta GET específica.

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

Para ejecutar esto, simplemente visite la URL "www.sitename.com/?linkupdate"

Esto está funcionando bien para mí hasta ahora ...

¿Este método tiene algún inconveniente? Solo me pregunto ...

    
respondido por el Sid 16.06.2017 - 08:10
1

Solo uso una única página de plantilla de producto personalizada que no estoy usando y no estoy conectado a nada en el servidor público.

Me gusta si tengo una página de testimonios que no está activa (en modo borrador, o lo que sea), pero conectada a una sola plantilla de página, por ejemplo, single-testimonial.php . Puedo colocar funciones allí, cargar la página a través de preview y la función o lo que se inicie una vez. También es muy fácil hacer modificaciones a la función en caso de depuración.

Es realmente fácil y lo prefiero a usar init porque tengo más control sobre cuándo y cómo se lanzó. Solo mi preferencia.

    
respondido por el bbruman 09.07.2017 - 00:13
0

En caso de que ayude, esto es lo que hice y funciona 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
}
    
respondido por el Adam Moss 19.11.2018 - 16:25

Lea otras preguntas en las etiquetas