Este artigo é uma explicação sobre o uso e divisão de hooks no WordPress. O artigo O que são Hooks? e alguns outros listados nesta página podem ajudar a entender melhor.
Eu também fiz uma série inteira sobre esse assunto lá no meu canal do YouTube com mais exemplos e mais profundidade. Se gostar, não esqueça de se inscrever!
Recapitulando
Se você caiu de paraquedas neste artigo é preciso só relembrar o que são hooks e sua importância. Hooks são formas de alterar o comportamento de um programa sem alterar seu código original, o que é especialmente importante quando se usa ferramenta de terceiros.
Podemos encarar os hooks como formas de estender uma funcionalidade, isto é, acrescentar algum comportamento a um plugin ou ao próprio core do WordPress para que eles se adequem à nossa necessidade.
Um exemplo prático antes de continuar
Quase todos os temas tem na tag <head> uma chamada à função wp_head(). Veja o código da função:
function wp_head() {
/**
* Print scripts or data in the head tag on the front end.
*
* @since 1.5.0
*/
do_action( 'wp_head' );
}
A função é meramente um hook, onde é possível “pendurar” qualquer coisa que se queira. O próprio WordPress faz uso do hook, como é possível ver no arquivo wp-includes/default-filters.php
, lá pela linha 200. O que mais importa neste momento é que você também pode fazer uso disto de um modo muito simples. No functions.php
do seu tema você pode incluir:
function exemplo_de_hook () {
echo '<!-- Só um comentário HTML -->';
}
add_action('wp_head', 'exemplo_de_hook');
Assim o comentário será impresso no cabeçalho do seu WordPress, sem que você tenha editado diretamente o código da função wp_head().
Divisão entre actions e filters
Os hooks no WordPress são classificados entre Ações (actions) e Filtros (filters). Em termos de execução eles são praticamente a mesma coisa (add_action é só uma chamada para add_filter), mas conceitualmente elas são um pouco diferentes.
Ações (actions)
As ações são chamadas através da função do_action
e são utilizadas em pontos onde se prevê a execução de alguma coisa, por exemplo, quando se salva um post (save_post), se deleta um usuário (delete_user), um pouco antes de exibir o carrinho de compras do woocommerce (woocommerce_before_cart) ou logo depois de criar uma tabela no tablepress (tablepress_event_added_table). Importante perceber como bons plugins deixam previstos eventos como estes e como plugins excelentes não só preveem como também fornecem documentação.
Filtros (filters)
Filtros são normalmente usados quando há a previsão para a alteração de uma variável e, por isso, normalmente espera-se um retorno de uma função adicionada com o add_filter()
. Observe a função nativa the_content()
, por exemplo, que imprime o conteúdo de um post:
function the_content( $more_link_text = null, $strip_teaser = false) {
$content = get_the_content( $more_link_text, $strip_teaser );
/**
* Filter the post content.
*
* @since 0.71
*
* @param string $content Content of the current post.
*/
$content = apply_filters( 'the_content', $content );
$content = str_replace( ']]>', ']]>', $content );
echo $content;
}
Simplificando, ela pega o conteúdo, aplica os filtros e imprime o resultado. No arquivo wp-includes/default-filters.php temos:
add_filter( 'the_content', 'wptexturize' );
add_filter( 'the_content', 'convert_smilies' );
add_filter( 'the_content', 'convert_chars' );
add_filter( 'the_content', 'wpautop' );
add_filter( 'the_content', 'shortcode_unautop' );
add_filter( 'the_content', 'prepend_attachment' );
Ou seja, o próprio WordPress pendura alguns filtros no the_content.
Pendurar e despendurar: add_filter e remove_filter
Tão importante quanto poder incluir funções nos hooks é a possibilidade de retirá-los conforme a nossa necessidade. Vamos supor, por exemplo, que não queiramos que o WordPress insira automaticamente parágrafos no nosso conteúdo. Basta que no nosso tema ou plugin escrevamos:
remove_filter('the_content', 'wpautop');
Algumas vezes não podemos retirar o filtro para todas as ocasiões, então podemos retirá-lo, usar a função com o apply_filters e incluí-lo novamente:
remove_filter('the_content', 'wpautop');
the_content();
add_filter('the_content', 'wpautop');
A ordem é importante
Como você já deve ter imaginado, a ordem em que as funções são executadas pode ser importante. Por exemplo: se você precisa criar um código para cada novo post e precisa que este código seja enviado por e-mail, a função que cria o código deve ser necessariamente chamada antes do envio. Para isso existe o parâmetro (opcional) de prioridades tanto nas actions quanto nos filters. Com valor padrão 10, as funções são executadas da menor prioridade para a maior, ou seja, funções adicionadas com prioridade 1 são executadas antes das adicionadas com prioridade 2. Este parâmetro também pode ser necessário para retirar funções dos hooks.
Necessário pensar também que os cenários de uso são extremamente variados e, por isso, o número de parâmetros esperados pelas funções também varia. Para isso também existe um parâmetro opcional.
Resumindo
O diagrama que eu criei no post sobre como remover “Protegido” e “Privado” dos títulos no WordPress pode ajudar a entender de uma forma mais gráfica como um filtro é usado.
Ações
add_action( $hook, $function_to_add, $priority, $accepted_args ); // Adiciona uma ação
remove_action( $tag, $function_to_remove, $priority ); // Retira uma ação
do_action( $tag, $arg ); // Executa todas as funções adicionadas com o add_action()
Filtros
add_filter( $tag, $function_to_add, $priority, $accepted_args ); // Adiciona um filtro
remove_filter( $tag, $function_to_remove, $priority ); // Retira um filtro
apply_filters( $tag, $value, $var ... ); // Aplica os filtros, mas não é uso comum.
// Filtro com echo:
echo apply_filters( $tag, $value );
// Filtro para uma variável:
$var = apply_filters( $tag, $value );
Gostou? Não se esqueça de comentar e deixar sua contribuição. Agora que você sabe mais sobre os hooks, que tal olhar suas aplicações nos widgets do WordPress?
Uso a versão 2.6.8 do Woocommerce, mas estou quebrando a cabeça para criar um plugin que atualiza o carrinho de compras quando houver a remoção de algum item. Acreditei que o problema fosse o cache da página, mas usando o W3 Cache Total com as configurações de não colocar a página do carrinho em cache não obtive resultado, agora procuro um meio de manter o carrinho sempre atualizado.
Olá Felipe,
Posso considerar então que em todo os “filters” devo ter um retorno de uma função? Esse retorno será sempre um “echo” ou posso ter um “return”?
Não sou um Jedi em PHP, mas gostei do artigo. Abriu a cabeça para algumas possíveis alterações no blog…
vlw!!
Oi Bruno!
Quando você inclui uma função com o add_filter essa função deverá ter “return” sim, para que o filtro seja aplicado junto com possíveis outros “pendurados” antes da sua função, ou seja, todas as funções que foram colocadas no hook vão alterando a variável e retornando para que a próxima possa fazer a mesma coisa. O “echo”, se for o caso, fica a cargo só de quem chama o apply_filters, isto é, depois que todos os filtros foram aplicados.
Se tiver algum tema ou se você teve alguma dúvida para montar o blog que você ache que valha a pena tratar aqui me fala, mesmo que eu não saiba corro atrás pra gente 🙂
Abs!