Ações do WordPress Explicadas: O Guia Completo do Desenvolvedor para a API de Hooks
WordPress Actions são um componente central da API de Hooks que permite aos desenvolvedores executar funções personalizadas em pontos precisamente definidos durante o ciclo de vida da requisição WordPress — sem nunca tocar nos ficheiros principais. Quando um hook de ação é disparado, cada função registada nesse hook é executada por ordem de prioridade, permitindo uma personalização modular, sustentável e segura para atualizações.
Se está a construir um plugin, a desenvolver um tema, ou a gerir uma instalação WordPress auto-hospedada num ambiente de VPS Hosting, dominar as Actions é indispensável. São o mecanismo principal pelo qual o próprio WordPress é arquitetado — não apenas uma ferramenta de extensão para terceiros.
Como as Actions do WordPress Funcionam Internamente
O WordPress mantém um registo global chamado $wp_filter, que armazena todos os hooks registados — tanto actions como filters. Quando do_action() é chamado, o WordPress procura a entrada desse hook em $wp_filter, ordena os callbacks registados por prioridade e executa-os sequencialmente.
A distinção crítica que muitos tutoriais ignoram: As Actions são do tipo “disparar e esquecer”. Executam callbacks mas descartam quaisquer valores de retorno. Se precisar de interceptar e modificar dados, esse é o trabalho dos Filters, não das Actions. Confundir os dois é um dos erros arquiteturais mais comuns no desenvolvimento de plugins WordPress.
O fluxo de execução é o seguinte:
- O núcleo do WordPress (ou um plugin/tema) chama
do_action( 'hook_name', ...$args ). - O WordPress resolve todos os callbacks registados em
hook_namea partir de$wp_filter. - Os callbacks são ordenados pelo seu valor
$priority(ascendente — números mais baixos disparam primeiro). - Cada callback é invocado com os argumentos fornecidos.
- Os valores de retorno são silenciosamente ignorados.
- A execução continua no código de origem após
do_action()retornar.
Esta arquitetura significa que um callback mal escrito registado num hook inicial como init pode bloquear toda a requisição. Faça sempre o perfil dos callbacks de hooks em ambiente de teste antes de implementar em produção.
Registar Actions com add_action()
A função add_action() regista um callable PHP num hook de ação com nome. A sua assinatura completa é:
add_action( string $hook_name, callable $callback, int $priority = 10, int $accepted_args = 1 ): trueParâmetros explicados:
$hook_name — O identificador de string exato do hook de ação (ex., wp_login, save_post).
$callback — Qualquer callable PHP válido: uma função com nome, uma função anónima, um método estático array( 'MyClass', 'method' ), ou um método de objeto array( $object, 'method' ).
$priority — Ordem de execução relativa a outros callbacks no mesmo hook. Padrão 10. Callbacks com a mesma prioridade são executados por ordem de registo.
$accepted_args — Quantos argumentos de do_action() passar ao seu callback. Padrão 1. Deve definir isto corretamente ou o seu callback receberá listas de argumentos truncadas.
Exemplo Básico: Ligar ao wp_login
function notify_admin_on_login( string $user_login, WP_User $user ): void {
$admin_email = get_option( 'admin_email' );
$subject = 'Login Alert: ' . $user_login;
$message = sprintf(
'User "%s" (ID: %d) logged in at %s.',
$user_login,
$user->ID,
current_time( 'mysql' )
);
wp_mail( $admin_email, $subject, $message );
}
// wp_login passes two arguments: $user_login (string) and $user (WP_User object)
add_action( 'wp_login', 'notify_admin_on_login', 10, 2 );
Note que accepted_args está definido como 2. Omitir isto e deixar o padrão 1 significa que o seu callback recebe apenas $user_login e nunca vê o objeto WP_User — um bug silencioso que é notoriamente difícil de rastrear.
Usar Métodos de Objeto e Closures
O desenvolvimento moderno de WordPress favorece encapsular a lógica dentro de classes:
class My_Plugin {
public function __construct() {
add_action( 'init', array( $this, 'register_post_types' ) );
add_action( 'save_post', array( $this, 'handle_save' ), 20, 3 );
}
public function register_post_types(): void {
register_post_type( 'product', array( /* args */ ) );
}
public function handle_save( int $post_id, WP_Post $post, bool $update ): void {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
// Custom save logic here
}
}
new My_Plugin();
Closures anónimas também funcionam, mas não podem ser removidas com remove_action() posteriormente porque o PHP não consegue comparar referências de funções anónimas de forma fiável. Use métodos com nome quando precisar da capacidade de cancelar o registo.
Remover Actions com remove_action()
Pode cancelar o registo de qualquer callback — incluindo os adicionados por outros plugins ou temas — usando remove_action(). A prioridade deve corresponder exatamente ao que foi usado em add_action():
remove_action( 'wp_head', 'wp_generator' ); // Removes WordPress version meta tag
Para métodos de objeto, precisa de uma referência à mesma instância do objeto:
// Inside a plugin that exposes its instance
global $my_plugin_instance;
remove_action( 'save_post', array( $my_plugin_instance, 'handle_save' ), 20 );
Um erro comum: chamar remove_action() antes de o add_action() original ter sido executado. Ligue sempre a sua remoção a uma action que dispara após o plugin alvo ser carregado — tipicamente plugins_loaded ou after_setup_theme.
Referência dos Hooks de Action Principais do WordPress
A tabela seguinte cobre os hooks de action operacionalmente mais significativos, o seu contexto de disparo e os seus casos de uso práticos.
Nome do Hook
Dispara Quando
Casos de Uso Típicos
Args Passados
muplugins_loaded
Plugins obrigatórios carregados
Bootstrapping inicial, constantes
0
plugins_loaded
Todos os plugins carregados
Verificações de compatibilidade entre plugins
0
init
Após carregamento do WP, antes dos cabeçalhos
Registar CPTs, taxonomias, regras de reescrita
0
wp_loaded
Após init, tudo carregado
Registo REST API, tarefas de inicialização tardias
0
wp_enqueue_scripts
Carregamento de recursos front-end
Enqueue de CSS/JS para temas e plugins
0
wp_head
Dentro da tag <head>
Meta tags, estilos inline, snippets de analytics
0
wp_footer
Antes de </body>
Scripts diferidos, pixels de rastreamento
0
admin_init
Carregamento de páginas de administração
Registo da Settings API, verificações de capacidade
0
admin_enqueue_scripts
Carregamento de recursos de administração
Enqueue de CSS/JS exclusivos do admin
1 ($hook_suffix)
save_post
Post guardado ou atualizado
Atualizações de meta, sincronização com API externa, notificações
3
wp_login
Utilizador autentica
Registo de auditoria, gestão de sessões
2
user_register
Novo utilizador criado
Emails de boas-vindas, sincronização com CRM, atribuição de funções
1 ($user_id)
wp_logout
Utilizador termina sessão
Limpeza de sessão, eventos de analytics
1 ($user_id)
switch_theme
Tema ativo alterado
Limpeza de cache, migração de opções
2
wp_trash_post
Post movido para o lixo
Limpeza de dados relacionados, sincronização externa
1 ($post_id)
rest_api_init
REST API inicializa
Registar rotas REST personalizadas
0
template_redirect
Antes do carregamento do template
Redirecionamentos, controlo de acesso
0
do_action() vs do_action_ref_array(): Quando Cada Um se Aplica
Ambas as funções disparam um hook de ação, mas diferem na forma como os argumentos são passados.
do_action()
A função padrão. Os argumentos são passados por valor — os callbacks recebem cópias.
do_action( 'my_plugin_after_import', $import_id, $result_count, $errors );
do_action_ref_array()
Os argumentos são passados como um array, e os objetos dentro desse array são passados por referência (os objetos PHP são sempre semelhantes a referências por padrão desde o PHP 5). Isto é principalmente útil para compatibilidade com código legado ou quando precisa explicitamente que os callbacks modifiquem uma estrutura de dados partilhada.
$context = array(
'post_id' => 42,
'meta' => array(),
);
do_action_ref_array( 'my_plugin_process_context', array( &$context ) );
// $context['meta'] may now be populated by hooked callbacks
Orientação prática: No PHP moderno (7.4+), a diferença comportamental entre os dois é mínima para objetos. Use do_action() por padrão. Recorra a do_action_ref_array() apenas quando integrar com código legado que o espera explicitamente, ou quando precisar que os callbacks modifiquem um valor primitivo (como um inteiro) passado por referência.
Criar e Documentar Hooks de Action Personalizados
Ao construir um plugin ou tema destinado a ser estendido por outros, deve definir os seus próprios hooks de ação. É assim que expõe uma superfície de API sem dar a terceiros acesso direto aos seus internos.
/**
* Fires after a custom import process completes.
*
* @since 1.0.0
*
* @param int $import_id The ID of the completed import batch.
* @param int $record_count Total number of records processed.
* @param array $errors Array of WP_Error objects, empty on full success.
*/
do_action( 'my_plugin_import_complete', $import_id, $record_count, $errors );
Documente sempre os seus hooks com um DocBlock diretamente acima de do_action(). É isto que alimenta o gerador de documentação para desenvolvedores WordPress e torna o seu plugin de nível profissional. Os desenvolvedores terceiros podem então ligar-se de forma limpa:
add_action( 'my_plugin_import_complete', function( int $import_id, int $count, array $errors ) {
if ( ! empty( $errors ) ) {
// Log errors to an external monitoring service
error_log( "Import {$import_id} completed with " . count( $errors ) . ' errors.' );
}
}, 10, 3 );
Actions vs Filters: Uma Comparação Definitiva
Esta é a distinção conceptual mais importante em toda a API de Hooks do WordPress.
Dimensão
Actions
Filters
Propósito principal
Executar efeitos secundários num ponto no tempo
Interceptar e modificar dados
Valor de retorno
Totalmente ignorado
Deve retornar o valor (modificado)
Função principal
do_action()
apply_filters()
Registo
add_action()
add_filter()
Uso típico
Enviar email, escrever na BD, enqueue de recursos
Modificar conteúdo de posts, alterar argumentos de query
Pode curto-circuitar?
Não (todos os callbacks são sempre executados)
Não (mas pode retornar antecipadamente dentro do callback)
Mutação de dados
Não é o padrão pretendido
Propósito principal
Regra arquitetural chave: Se está a usar add_filter() mas não está a retornar um valor do seu callback, introduziu um bug — o valor filtrado tornar-se-á null ou false dependendo do contexto. Inversamente, se está a usar add_action() e a depender de um valor de retorno, está a usar incorretamente a API.
Conflitos de Prioridade e Ordem de Execução
A gestão de prioridades torna-se crítica em ecossistemas de plugins complexos. Considere um cenário onde o WooCommerce, um plugin de cache e o seu código personalizado se ligam todos ao save_post:
// WooCommerce hooks at priority 10 (default)
// Your inventory sync needs WooCommerce data to already be saved
add_action( 'save_post_product', 'sync_inventory_to_erp', 99 );
// A cache purge should happen last, after all data is written
add_action( 'save_post', 'purge_varnish_cache', 9999 );
Casos extremos a conhecer:
Prioridades negativas são válidas no WordPress. add_action( 'init', 'my_func', -1 ) dispara antes de qualquer coisa na prioridade 0 ou 10.
Mesma prioridade, múltiplos callbacks — executam na ordem em que add_action() foi chamado. A ordem de carregamento dos plugins (determinada pelo nome do ficheiro alfabeticamente, ou plugins Plugin Order) afeta portanto o comportamento.
Hooks recursivos — chamar do_action() para o mesmo hook dentro de um callback para esse hook é tecnicamente possível mas cria loops infinitos. O WordPress não protege contra isto.
Registo tardio de hooks — se chamar add_action( 'init', ... ) após init já ter disparado, o seu callback nunca será executado nessa requisição. Esta é uma fonte frequente de bugs em código que é executado condicionalmente.
Padrões de Produção do Mundo Real
Padrão 1: Sistema de Eventos Desacoplado
Use actions personalizadas para desacoplar componentes de plugins, evitando chamadas de função diretas entre módulos:
// In your order processing module
do_action( 'my_shop_order_paid', $order_id, $payment_method, $amount );
// In your email module (separate file, no direct dependency)
add_action( 'my_shop_order_paid', 'send_payment_confirmation_email', 10, 3 );
// In your analytics module (separate file, no direct dependency)
add_action( 'my_shop_order_paid', 'track_conversion_event', 20, 3 );
Este padrão significa que pode desativar o módulo de analytics inteiramente sem tocar no código de processamento de encomendas.
Padrão 2: Registo Condicional de Hooks
Evite registar hooks incondicionalmente ao nível superior. Limite-os ao contexto onde são necessários:
add_action( 'admin_init', function() {
// Only register these hooks in the admin context
add_action( 'admin_enqueue_scripts', 'my_plugin_admin_assets' );
add_action( 'save_post', 'my_plugin_validate_custom_fields', 10, 2 );
} );
Padrão 3: Actions de Uma Vez com remove_action() Dentro do Callback
function my_plugin_run_once(): void {
// Do something that must only happen once per request
update_option( 'my_plugin_initialized', true );
// Deregister itself to prevent re-execution if the hook fires again
remove_action( 'wp_loaded', 'my_plugin_run_once' );
}
add_action( 'wp_loaded', 'my_plugin_run_once' );
Considerações de Desempenho em Ambientes Geridos
Em instalações WordPress de alto tráfego — quer a correr num plano de VPS Hosting ou num Servidor Dedicado — o custo cumulativo de hooks mal otimizados é mensurável.
Ferramentas de perfil a usar:
Plugin Query Monitor: Mostra cada hook que disparou, cada callback que foi executado e o tempo de execução por callback.
Xdebug + KCacheGrind: Para perfil aprofundado dos caminhos de execução de callbacks.
New Relic APM: Para monitorização de desempenho de hooks ao nível de produção.
Princípios de otimização:
Mova operações dispendiosas (queries de base de dados, pedidos HTTP, I/O de ficheiros) para fora de hooks que disparam em cada carregamento de página (init, wp_head) e para hooks que disparam apenas quando necessário (save_post, user_register).
Use transients ou cache de objetos para memoizar resultados de computações dispendiosas dentro de callbacks de hooks.
Evite registar centenas de chamadas add_action() incondicionalmente no momento de carregamento do plugin. Registe hooks de forma lazy apenas quando a página de administração ou contexto relevante estiver ativo.
Em servidores com OPcache ativado (que todos os ambientes PHP corretamente configurados devem ter), a sobrecarga do próprio registo de hooks é negligenciável — o custo está no que os callbacks *fazem*, não no registo.
Se gere a sua própria stack WordPress, garantir que o seu servidor corre PHP 8.1+ com OPcache, um cache de bytecode e um cache de objetos como Redis ou Memcached terá um impacto de desempenho muito maior do que micro-otimizar prioridades de hooks.
Actions do WordPress no Contexto do Desenvolvimento de Plugins e Temas
Ao desenvolver um plugin destinado ao repositório WordPress.org ou distribuição comercial, o seu uso da API de Hooks determina diretamente a qualidade do código e as classificações de compatibilidade.
Melhores práticas para uso de hooks de nível de produção:
Verifique sempre DOING_AUTOSAVE dentro de callbacks save_post para evitar executar lógica dispendiosa em gravações automáticas.
Verifique nonces e capacidades dentro de qualquer callback de hook que processe dados submetidos pelo utilizador. Nunca confie que o próprio hook fornece segurança.
Use current_action() para determinar qual hook específico disparou o seu callback quando a mesma função está registada em múltiplos hooks.
Coloque namespace nos nomes dos seus hooks personalizados para evitar colisões: my_plugin_event_name, não event_name.
Versione os seus hooks na documentação para que os desenvolvedores saibam quando um hook foi introduzido e quando pode ser descontinuado.
Para equipas que implementam WordPress em infraestrutura com Painéis de Controlo VPS, manter ambientes de teste que espelhem a produção é essencial para testar com segurança as interações de hooks antes da implementação.
Proteger a Sua Instalação WordPress Juntamente com Actions Personalizadas
Hooks de ação personalizados que processam dados externos, gerem eventos de autenticação ou interagem com o sistema de ficheiros introduzem superfície de segurança. Combine o desenvolvimento dos seus hooks com um ambiente de hospedagem devidamente protegido.
Certifique-se de que a sua instalação WordPress usa HTTPS — um Certificado SSL é obrigatório para qualquer site que gerencie autenticação de utilizadores ou submissões de formulários. Callbacks de hooks que disparam em wp_login ou user_register estão a processar dados sensíveis pela rede; sem TLS, esses dados ficam expostos independentemente de quão bem o seu código PHP está escrito.
Adicionalmente, se o seu plugin usa wp_mail() dentro de callbacks de ação (um padrão comum para notificações), a configuração e reputação de correio do seu servidor afetam diretamente a entregabilidade. Considere uma solução dedicada de Email Hosting com registos SPF, DKIM e DMARC adequados em vez de depender do sendmail ao nível do servidor.
Matriz de Decisão Técnica e Principais Conclusões
Use esta lista de verificação ao implementar Actions do WordPress em qualquer projeto:
Registo de hooks:
Defina $accepted_args explicitamente sempre que o hook passa mais de um argumento
Use valores de prioridade deliberadamente — documente por que são escolhidas prioridades não padrão
Registe hooks dentro de construtores de classe ou métodos register_hooks() dedicados, nunca no âmbito global de um ficheiro de plugin
Limite o registo de hooks ao contexto onde é necessário (admin, front-end, REST API)
Implementação de callbacks:
Verifique sempre DOING_AUTOSAVE, DOING_CRON e wp_is_json_request() onde relevante
Verifique nonces com check_admin_referer() ou check_ajax_referer() antes de processar qualquer entrada do utilizador
Nunca dependa de valores de retorno de do_action() — use filters se precisar de dados de volta
Use current_action() quando um callback serve múltiplos hooks
Design de hooks personalizados:
Coloque namespace em todos os nomes de hooks personalizados com o prefixo do seu plugin/tema
Documente cada hook personalizado com um DocBlock completo acima de do_action()do_action() em vez de do_action_ref_array() a menos que tenha uma razão específicaDesempenho e manutenção:
- Faça o perfil dos callbacks de hooks com Query Monitor antes de implementar em produção
- Evite queries de base de dados dentro de hooks que disparam em cada requisição
- Use
remove_action()para limpar hooks de terceiros que conflituam com a sua implementação - Teste as interações de hooks num ambiente de teste que espelhe a infraestrutura de produção
FAQ
Qual é a diferença entre add_action() e add_filter() no WordPress?
add_action() regista um callback para executar efeitos secundários num ponto específico da execução — o valor de retorno é descartado. add_filter() regista um callback para receber, modificar e retornar um valor. Usar um onde o outro é apropriado é um bug funcional: um callback de filter que não retorna um valor irá anular os dados filtrados.
Por que o meu callback add_action() não está a disparar?
As causas mais comuns são: (1) o nome do hook está mal escrito, (2) add_action() é chamado após o hook já ter disparado na requisição atual, (3) $accepted_args é demasiado baixo e o callback recebe dados errados causando um erro PHP silencioso, ou (4) uma verificação condicional dentro do callback está a impedir a execução. Use Query Monitor para verificar se o hook disparou e se o seu callback foi registado.
Posso usar add_action() dentro de outro callback de ação?
Sim, e este é um padrão comum. Por exemplo, registar hooks dentro de plugins_loaded ou init para garantir que as dependências estão disponíveis. No entanto, o hook interno deve disparar após o externo para que o registo tenha efeito.
O que controla realmente o parâmetro $priority?
Controla a ordem em que múltiplos callbacks registados no mesmo hook são executados. Números mais baixos disparam primeiro. O padrão é 10. Os valores válidos incluem inteiros negativos. Quando dois callbacks partilham a mesma prioridade, executam na ordem em que foram registados via add_action().
Como removo com segurança uma ação adicionada por um plugin de terceiros?
Ligue a sua chamada remove_action() a uma ação que dispara após o plugin ter sido carregado — tipicamente plugins_loaded com alta prioridade, ou after_setup_theme. Deve corresponder exatamente ao nome do hook, referência do callback e prioridade usados na chamada add_action() original. Para métodos de objeto, precisa de acesso à mesma instância do objeto, que plugins respeitáveis expõem através de uma variável global ou de um método estático get_instance().
