Qual é a sua melhor prática para executar scripts únicos?

31

O problema

Todos nós estamos em uma situação como essa, e muitas perguntas neste site precisam de uma solução como essa. Você precisa atualizar um banco de dados, inserir muitos dados automaticamente, converter meta_keys ou algo semelhante.

É claro que, em um sistema em execução baseado em práticas recomendadas, isso não deve acontecer.

Mas, ao fazê-lo, adoraria ouvir a sua solução pessoal para este problema e porque escolheu a sua.

A questão

Como você implementa scripts únicos em sua instalação (em execução) do WordPress?

A questão aqui é principalmente pelas seguintes razões:

  • Scripts que inserem dados não devem ser executados mais de uma vez
  • Scripts que exigem muitos recursos não devem ser executados no momento em que não puderem ser monitorados
  • Eles não devem ser executados por acidente

A razão que eu pergunto

Eu tenho minha própria prática, vou postar nas respostas. Como não sei se é a melhor solução, gostaria de saber sobre a sua. Além disso, esta é uma pergunta que é feita muitas vezes no contexto de outras questões, e seria ótimo ter um recurso para coletar as idéias.

ansioso para aprender com você:)

    
por fischi 29.01.2014 / 17:24
fonte

11 respostas

15

Eu, por mim mesmo, uso uma combinação de:

  • um arquivo dedicado ao script único
  • usando um transiente para impedir que o script seja executado acidentalmente mais de uma vez
  • usando o recurso de gerenciamento ou controle de usuário para garantir que o script seja executado apenas por mim.

Estrutura

Eu uso um arquivo ( onetime.php ) na minha pasta de inclusão inc , que está incluso no functions.php , e é deletado depois do uso.

include( 'inc/onetime.php' );

O arquivo para o script em si

Na minha onetime.php minha função f711_my_onetime_function() é colocada. Como poderia ser qualquer função. Eu suponho que seu script foi testado e funciona corretamente.

Para conseguir o controle sobre a execução do script, eu uso os dois

Controle de capacidade

Para impedir que outros usuários executem meu script acidentalmente:

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.

um transiente

para me impedir de executar acidentalmente o script mais de uma vez.

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

O arquivo para executar o script na minha função f711_my_onetime_function() ficaria assim:

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

A razão pela qual eu configurei o transiente imediatamente após a verificação, se ele existir, é que eu quero que a função seja executada após o script ter sido bloqueado de ser usado duas vezes.

Se eu precisar de qualquer saída da minha função, imprima-a como um comentário no rodapé ou, às vezes, até mesmo filtrarei o conteúdo.

O tempo de bloqueio está definido para 10 minutos, mas pode ser ajustado às suas necessidades.

Limpeza

Após a execução bem-sucedida do meu script, excluo o include do functions.php e remova o onetime.php do servidor. Como usei um tempo limite para o transiente, não preciso limpar o banco de dados, mas é claro que você também pode excluir o transiente depois de remover o arquivo.

    
por fischi 29.01.2014 / 17:24
fonte
12

Você também pode fazer isso:

execute onetime.php e renomeie após a execução.

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');
}
    
por Ravinder Kumar 05.02.2014 / 20:58
fonte
7

Eu criei um script Phing de linha de comando para isso, não é nada especial além de carregar um script externo para ser executado. O motivo pelo qual usei o CLI é porque:

  • Eu não quero que ele seja carregado por engano (preciso digitar um comando)
  • É seguro, pois pode ser executado fora da raiz da Web, em outras palavras, pode afetar o WP, mas o WP não pode acessar o script de nenhuma maneira.
  • Ele não adiciona nenhum código ao WP ou ao próprio DB.
require('..path to ../wp-blog-header.php');
//bunch of WP globals
define('WP_USE_THEMES', false);
//custom code

Então você pode usar o Phing, ou o PHP CLI e dormir à noite. O WP-CLI também é uma boa alternativa, embora eu esqueça que você pode usá-lo fora da raiz da web.

Como este é um post popular, aqui está um exemplo do script: enlace (run.php)

    
por Wyck 06.02.2014 / 03:54
fonte
5

Outra maneira bastante simples de executar um script único é fazer isso por meio de um plugin MU.

Coloque o código em algum arquivo PHP (por exemplo, one-time.php ) que você carregou na pasta dos seus plugins MU (por padrão /wp-content/mu-plugins ), ajuste as permissões do arquivo, execute o plugin (ou seja, de acordo com o gancho escolhido , basicamente você só tem que visitar o frontend / backend), e está tudo pronto.

Aqui está um clichê:

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

Sem os comentários e outras coisas, é assim:

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

Às vezes, usei uma função conectada à desativação do plug-in.

Veja aqui Atualizar links antigos Para o tipo de postagem personalizado Permalinks bonito

Uma vez que apenas os administradores podem ativar plugins, há uma verificação de capacidade como um efeito colateral.

Não há necessidade de excluir o arquivo, uma vez desativado, ele não será incluído pela redação de palavras. Além disso, se você quiser correr novamente, você pode. Ativando e desativando novamente.

E às vezes eu usei transiente usado como na resposta @fischi. Por exemplo. aqui consulta para criar produtos de woocommerce a partir de imagens ou aqui Excluir / substituir as tags img no conteúdo postado para postagens publicadas automaticamente

Uma combinação de ambos pode ser uma alternativa.

    
por gmazzap 05.02.2014 / 21:14
fonte
3

Em condições ideais, eu faria ssh no servidor e executaria a função usando wp-cli.

Isso geralmente não é possível, então eu tenho a tendência de definir uma variável $ _GET e conectá-la ao 'init', por exemplo:

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

depois, clique em

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

e desative o gancho quando terminar.

    
por djb 05.02.2014 / 20:38
fonte
3

Definitivamente você pode, basta criar seu código de tempo único como um plugin.

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

Problema Como eu ativo este plugin sem clicar em Ativar link?

adicione apenas activate_plugins('onetime/index.php'); em functions.php

ou O uso deve usar plugins, enlace

Tente com ações diferentes como quando deseja executar o plug-in onetime,

  1. admin_init - depois do admin init

  2. init --express do wordpress

  3. wp - quando o wordpress é carregado

por Amit Sukapure 08.02.2014 / 17:28
fonte
2

Outra maneira é definir uma wp_option global quando o trabalho estiver concluído e verificar essa opção toda vez que o gancho init for executado.

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, você não precisa ter esse código para sempre (mesmo que seja uma leitura simples do banco de dados), então você provavelmente poderá remover o código quando o trabalho estiver concluído. Além disso, você pode alterar manualmente este valor de opção para 0 se precisar executar novamente o código.

    
por Mauro Mascia 29.12.2014 / 12:22
fonte
1

Minha abordagem é um pouco diferente sobre isso. Eu gosto de adicionar meu script de uma só vez como uma função no function.php do meu tema e executá-lo em uma consulta GET específica.

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

Para executar isso, basta acessar a URL "www.sitename.com/?linkupdate"

Isso está funcionando bem para mim até agora ...

Esse método tem alguma desvantagem? Apenas pensando ...

    
por Sid 16.06.2017 / 08:10
fonte
1

Uso apenas uma única página de modelo de produto personalizado que não estou usando e não está conectada a nada no servidor público.

Como se eu tivesse uma página de depoimento que não estivesse ativa (no modo de rascunho ou qualquer outra), mas conectada a um único modelo de página, por exemplo single-testimonial.php - posso colocar funções lá, carregar a página por meio de preview e a função ou o que for lançado uma vez. Também é muito fácil fazer modificações na função em caso de depuração.

É realmente fácil e eu prefiro usar init porque tenho mais controle sobre quando e como é lançado. Apenas minha preferência.

    
por bbruman 09.07.2017 / 00:13
fonte
0

Apenas para ajudar, foi o que fiz e funciona bem:

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
}
    
por Adam Moss 19.11.2018 / 16:25
fonte