Quando usar add_action ('init') vs add_action ('wp_enqueue_scripts')

10

No functions.php do meu tema, estou chamando um add_action para obter uma medida de controle sobre onde o jquery é carregado (no rodapé, juntamente com os outros scripts do meu tema).

O problema que estou tendo é que, quando uso add_action ('wp_enqueue_scripts'), ele parece disparar apenas se nenhum plug-in estiver carregado. No entanto, o método add_action ('init') funciona em todos os casos.

Não me lembro por quê, mas acredito que add_action ('wp_enqueue_scripts') seja preferida nesse caso. Se isso for verdade, como posso fazê-lo funcionar em todos os casos?

Em functions.php

//if(!is_admin()){add_action('init', 'my_theme_init');} //THIS WORKS ALL THE TIME
//add_action('wp_enqueue_scripts', 'my_theme_init'); //THIS ONLY WORKS WHEN NO PLUGINS PRESENT

if(!is_admin())
{
    require_once(TEMPLATEPATH . '/functions_public.php');   
}

Em functions_public.php

function my_theme_init()
{

/* PREVENT DUPLICATE COPIES OF JQUERY FROM PLUGINS
**************************************************/
wp_deregister_script('jquery');

/* LOAD THE LOCAL WORDPRESS COPY OF JQUERY AND THEME CUSTOM SCRIPTS IN THE FOOTER
***********************************************/
wp_register_script('jquery', get_bloginfo('template_directory').'/scripts.mythemescripts.js',false,false,true);

wp_enqueue_script('jquery');

}

O segundo método, usando add_action ('wp_enqueue_scripts'), aparentemente não é executado em condições em que existe um plug-in que grava dependências de script no tema.

N2Mystic
fonte
5
Por favor, não registar a sua própria cópia do jQuery - usar a versão fornecida com o WordPress, então você vai acabar quebrando plug-ins :)
Stephen Harris
Concordo, na verdade, estou usando o que é enviado com o jQuery. Estou apenas carregando-o em um único .js (mythemescripts.js) junto com os outros arquivos js que meu tema precisa, a fim de reduzir as solicitações de http.
N2Mystic
Em todos os navegadores, uma vez que o script é solicitado no seu site uma vez, ele é armazenado em cache localmente. Você só terá a solicitação HTTP extra no carregamento da primeira página. Se você combinar todos os scripts em um único, será forçado a mudar isso sempre que o WP lançar uma atualização com uma nova versão do jQuery. Este == pesadelo de manutenção.
EAMann
2
@EAMann, quando o tema é instalado pela primeira vez e, toda vez que minha página de opções de temas é salva, reescrevo o mythemescripts.js, carregando a cópia mais recente da biblioteca jquery. Se o usuário atualizar sua versão do WP, minha rotina de opções de tema carregará o jquery que vem com isso. É sempre atualizado.
N2Mystic
O problema ainda ocorre quando uma chamada de jquery está contida no corpo do documento antes do rodapé. Aparentemente, o jQuery (documento) .ready é acionado antes do script .js ser carregado no rodapé.
N2Mystic

Respostas:

26

Muitos desenvolvedores de plugins não fazem as coisas da maneira certa. O caminho certo é ligar wp_enqueue_scriptscomo você está tentando fazer.

No entanto, aqui está a ordem dos ganchos executados em uma solicitação típica:

  • muplugins_loaded
  • Registered_taxonomy
  • Registered_post_type
  • plugins_loaded
  • sanitize_comment_cookies
  • setup_theme
  • load_textdomain
  • after_setup_theme
  • auth_cookie_malformed
  • auth_cookie_valid
  • set_current_user
  • iniciar
  • widgets_init
  • register_sidebar
  • wp_register_sidebar_widget
  • wp_default_scripts
  • wp_default_stypes
  • admin_bar_init
  • add_admin_bar_menus
  • wp_loaded
  • parse_request
  • send_headers
  • parse_query
  • pre_get_posts
  • posts_selection
  • wp
  • template_redirect
  • get_header
  • wp_head
  • wp_enqueue_scripts
  • wp_print_styles
  • wp_print_scripts
  • ... muito mais

O fato é que vários desenvolvedores foram instruídos originalmente a se conectarem initpara enfileirar seus scripts. Antes de começarmos wp_enqueue_script, essa era a maneira "correta" de fazer as coisas, e os tutoriais que perpetuam a prática ainda estão flutuando na Internet, corrompendo os bons desenvolvedores.

Minha recomendação seria dividir sua função em duas partes. Coloque seu wp_deregister_script/ wp_register_scriptno initgancho e use o wp_enqueue_scriptsgancho quando enfileirar o jQuery.

Isso manterá você no mundo de "fazer o certo" para enfileirar seus scripts e ajudará a protegê-lo das centenas de desenvolvedores que ainda "fazem de errado" trocando o jQuery pela sua versão concatenada antes de adicioná-lo à fila .

Você também deseja adicionar seu initgancho com alta prioridade:

add_action( 'init', 'swap_out_jquery', 1 );
function swap_out_jquery() {
    // ...
}
EAMann
fonte
2
Eu recomendaria isso, mas percebi que o OP estava cancelando o registro do jQuery e, em seguida, registrando um script diferente por completo e chamando-o de "jquery". Eu não acho que seja uma boa prática para incentivar, e acho que uma rota melhor seria simplesmente desenfileirar o jQuery completamente e enfileirar o script personalizado usando um identificador personalizado .
Chip Bennett
Aponte para observar sobre a priorityadição de ações. Tudo depende de como você vê a prioridade. Se você deseja que o seu seja executado "primeiro", um número menor é melhor - uma prioridade mais alta na ordem da fila de execução. Mas se você deseja que o efeito de sua função tenha precedência sobre outras, você deseja que seja executado mais tarde - portanto, uma prioridade mais alta por "efeito". E, nesse caso, é provavelmente um número maior que você deseja. Mesmo que haja pouco mérito em trocar a versão RTM do jquery, como sugere o comentarista anterior.
Paul G.
3

Existem vários problemas aqui, que são inter-relacionados.

  1. O gancho de ação correto a ser usado para enfileirar scripts é wp_enqueue_scripts
  2. Para imprimir scripts no rodapé wp_enqueue_script(), defina o $footerparâmetro comotrue
  3. Suas add_action( $hook, $callback )chamadas não devem ser agrupadas em nada; deixá-los executar diretamente defunctions.php
  4. Você deve colocar seus is_admin()cheques condicionais dentro do seu retorno de chamada
  5. Você não deve cancelar o registro de scripts do pacote principal de um Tema, por qualquer motivo. Mesmo que seu objetivo seja a concatenação de scripts, esse é o território do Plugin .
  6. Se você deve cancelar o registro do jquery, wp_enqueue_scriptsé tarde demais . Divida seu código de cancelamento de registro / registro em um retorno de chamada conectado init.
  7. Chamar outro script de "jquery" também provavelmente não é uma boa prática. Sua melhor aposta seria simplesmente desenfileirar o jQuery e carregar seu script personalizado.
  8. Certifique-se de colocar uma prioridade baixa no seu retorno de chamada, para substituir os Plug-ins
  9. Use em get_template_directory()vez deTEMPLATEPATH

Juntando tudo:

<?php
function wpse55924_enqueue_scripts() {
    if ( ! is_admin() ) {

        // Dequeue jQuery
        wp_dequeue_script( 'jquery' );

        // Register/enqueue a custom script, that includes jQuery
        wp_register_script( 'mythemescripts', get_template_directory_uri() . '/scripts.mythemescripts.js', false, false,true );
        wp_enqueue_script( 'mythemescripts' ); 
    }
}
add_action( 'wp_enqueue_scripts', 'wpse55924_enqueue_scripts', 99 );

Mas, novamente: essa realmente não é a melhor abordagem. Sua melhor aposta é simplesmente remover os retornos de chamada do plugin add_action () que cancelam o registro do jQuery principal - ou usar Plugins que não fazem algo tão imprudente quanto substituir o jQuery incluído no pacote principal.

Chip Bennett
fonte
O OP está combinando a versão distribuída do WP do jQuery com alguns outros scripts programaticamente, de modo que apenas uma solicitação HTTP seja feita pelo seu tema para carregar todos os arquivos JS. Portanto, os scripts personalizados contêm jQuery e não quebram nada se carregados dessa maneira. A substituição do identificador 'jquery' registrado é necessária para impedir o carregamento do jQuery duas vezes - uma vez no arquivo JS combinado e novamente por qualquer plug-in que tente enfileirar o jQuery por conta própria.
EAMann
É semântica e praticamente _doing_it_wrong()chamar algo que não é apenas jQuery "jQuery". Além disso: o jQuery em si pode simplesmente ser retirado da fila para garantir que não seja carregado duas vezes. A wp_dequeue_script()chamada só precisa ocorrer com uma prioridade suficiente para garantir que nada a enfileire posteriormente.
Chip Bennett