DesenvolvedorWordPress WhatsApp

Como criar um plugin WordPress do zero (do jeito certo)

Um plugin é a forma correta de adicionar funcionalidade ao WordPress sem refém do tema e sem tocar no núcleo. Veja a estrutura mínima, o cabeçalho obrigatório, as guardas de segurança e os hooks de ativação — com código pronto para usar.

Precisa de um plugin sob medida?

Atualizado em 19/06/2026

Toda customização de funcionalidade que você quer manter quando trocar de tema, atualizar o site ou migrar de servidor deveria estar em um plugin. Um plugin é apenas um diretório com pelo menos um arquivo PHP que o WordPress reconhece por um comentário especial no topo. A partir daí, ele se "pendura" no WordPress por meio de hooks. Este guia mostra, na ordem prática, como montar um do zero seguindo os padrões oficiais — para que o seu código não quebre na próxima atualização.

1. Por que um plugin, e não o functions.php do tema

A pergunta aparece sempre: "por que não jogo esse código no functions.php do tema?". Porque o functions.php pertence ao tema. No dia em que você trocar de tema, ou em que o tema receber uma atualização que sobrescreva o arquivo, todo o código somado ali some junto. Um plugin é independente: continua ativo mesmo que a aparência mude.

A linha divisória é clara:

2. Estrutura mínima de um plugin

Um plugin pode ser um único arquivo, mas o padrão recomendado é uma pasta própria dentro de wp-content/plugins/, com o arquivo principal de mesmo nome:

wp-content/
└── plugins/
    └── meu-plugin/
        ├── meu-plugin.php     <-- arquivo principal (com o cabeçalho)
        └── uninstall.php      <-- limpeza ao desinstalar (opcional)

Use sempre minúsculas e hífens no nome da pasta e do arquivo (o slug do plugin). À medida que cresce, você adiciona subpastas como includes/, admin/ e assets/, mas o WordPress só exige uma coisa para reconhecer o plugin: o cabeçalho no arquivo principal.

3. O cabeçalho do plugin (obrigatório)

O WordPress identifica um plugin lendo um bloco de comentário no topo do arquivo principal. Sem ele — mais precisamente, sem a linha Plugin Name: — o arquivo nem aparece na tela de Plugins. Junte a isso a guarda de acesso direto e você tem o esqueleto inicial:

<?php
/**
 * Plugin Name:       Meu Plugin
 * Description:        Faz algo útil via hooks, sem mexer no tema.
 * Version:           1.0.0
 * Requires at least: 6.0
 * Requires PHP:      7.4
 * Author:            Roger Takemiya
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       meu-plugin
 */

// Guarda: impede o acesso direto ao arquivo pela URL.
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

Cada linha do cabeçalho tem função: Plugin Name é a única obrigatória; Version controla cache e atualizações; Text Domain liga o plugin às traduções; License declara a licença (o WordPress.org exige compatível com a GPL). Os campos e a sintaxe exata estão documentados em Header Requirements.

4. A guarda de segurança: ABSPATH

A constante ABSPATH só existe quando o WordPress foi carregado. Se alguém abrir meu-plugin.php direto no navegador, ela não estará definida e a linha if ( ! defined( 'ABSPATH' ) ) exit; encerra o script imediatamente — sem executar nada, sem vazar caminhos ou variáveis. Essa guarda deve estar no topo de todo arquivo PHP do plugin, não só no principal. É a primeira camada de uma estratégia maior de segurança no código, que inclui sanitizar entradas e escapar saídas.

5. Prefixe tudo (evite colisões)

Todos os plugins, o tema e o núcleo compartilham o mesmo escopo global. Se dois deles declararem uma função setup() ou um add_option( 'config', ... ), você terá um erro fatal ou dados sobrescritos. A defesa é prefixar tudo com algo único do seu projeto:

Escolha um prefixo curto e exclusivo (4 a 5 letras costuma bastar) e seja consistente. É barato adotar desde o início e caro de corrigir depois que o plugin já está em produção.

6. Use hooks, não código solto

Dentro do arquivo principal, o seu código não deve rodar "solto" — ele deve se registrar em hooks e aguardar o WordPress chamá-lo no momento certo. Assim você garante que as funções do WordPress já existam e que o seu código rode no contexto adequado (front-end, admin, cron). Um exemplo: enfileirar um script só no front-end.

<?php
add_action( 'wp_enqueue_scripts', 'dwp_enfileirar_assets' );

function dwp_enfileirar_assets() {
    wp_enqueue_script(
        'dwp-frontend',
        plugins_url( 'assets/app.js', __FILE__ ),
        array(),                 // dependências
        '1.0.0',                 // versão (cache-busting)
        true                     // carregar no rodapé
    );
}

Repare no plugins_url( 'assets/app.js', __FILE__ ): ele monta a URL correta para um arquivo do plugin a partir do caminho do arquivo atual, sem você fixar URLs na unha. É a forma certa de referenciar assets dentro de um plugin.

7. Ativação, desativação e desinstalação

O ciclo de vida do plugin tem três momentos distintos, e confundi-los é um erro comum:

<?php
register_activation_hook( __FILE__, 'dwp_na_ativacao' );
register_deactivation_hook( __FILE__, 'dwp_na_desativacao' );

function dwp_na_ativacao() {
    // Cria uma opção inicial (sem sobrescrever se já existir).
    add_option( 'dwp_versao_banco', '1.0.0' );

    // Agenda um evento de cron diário, se ainda não houver.
    if ( ! wp_next_scheduled( 'dwp_evento_diario' ) ) {
        wp_schedule_event( time(), 'daily', 'dwp_evento_diario' );
    }

    // Se o plugin registra rewrite rules/CPT, atualize a estrutura.
    flush_rewrite_rules();
}

function dwp_na_desativacao() {
    // Limpa o agendamento — mas NÃO apague dados na desativação.
    wp_clear_scheduled_hook( 'dwp_evento_diario' );
    flush_rewrite_rules();
}

O primeiro argumento de register_activation_hook() é sempre __FILE__ do arquivo principal do plugin — é assim que o WordPress associa o callback ao plugin certo. Detalhes e ressalvas (o hook roda antes de o plugin estar totalmente carregado) estão em register_activation_hook().

uninstall.php: limpeza ao desinstalar

Para a desinstalação, o método preferido é criar um arquivo uninstall.php na raiz do plugin. O WordPress o executa automaticamente quando o usuário clica em "Excluir", mas somente nesse contexto — por isso a verificação da constante WP_UNINSTALL_PLUGIN no topo é obrigatória, para impedir que o arquivo rode em qualquer outra situação:

<?php
// uninstall.php — executado apenas ao excluir o plugin.
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
    exit;
}

// Remove as opções criadas pelo plugin.
delete_option( 'dwp_versao_banco' );

// Em multisite, repita a limpeza por site, se necessário.
// Remova também meta de posts/usuários e tabelas próprias aqui.

Nunca apague dados do usuário na desativação: ele pode estar apenas testando outro plugin temporariamente e espera reencontrar tudo ao reativar. A remoção destrutiva pertence ao uninstall.php, que só roda na exclusão definitiva — e ainda assim convém oferecer uma opção para o usuário decidir se quer mesmo apagar os dados.

8. Onde colocar o código: plugin × tema × mu-plugin

Resumindo a decisão de onde cada trecho deve morar:

LocalSobrevive à troca de tema?Pode desativar no painel?Quando usar
Plugin (plugins/)SimSimFuncionalidade reutilizável: CPTs, shortcodes, integrações, regras de negócio
functions.php do temaNãoApenas o que é específico daquele visual: menus, sidebars, suportes do tema
mu-plugin (mu-plugins/)SimNão (carrega sempre)Código crítico que nunca deve ser desligado: regras de rede, configs forçadas

9. Boas práticas que separam amador de profissional

Com esse esqueleto — cabeçalho, guarda ABSPATH, prefixo, hooks e os ganchos de ciclo de vida — você já tem um plugin que o WordPress reconhece, que sobrevive a atualizações e que não atrapalha outros plugins. O resto é construir a funcionalidade em cima dessa base sólida.

Precisa de um plugin WordPress sob medida?

Desenvolvo plugins do zero e organizo customizações que hoje estão soltas no tema, seguindo os padrões oficiais do WordPress. Me chame no WhatsApp.

WhatsApp: (43) 99932-9697

ou e-mail: [email protected]

Perguntas frequentes

Por que não colocar tudo no functions.php do tema?

Porque o functions.php pertence ao tema. Se você trocar de tema, ou se o tema receber uma atualização que sobrescreva o arquivo, suas customizações desaparecem. Um plugin é independente do tema: continua ativo mesmo que você mude a aparência do site. A regra prática é simples — código de apresentação (o que é específico daquele visual) fica no tema; código de funcionalidade (que deve sobreviver à troca de tema) fica em um plugin.

O que o WordPress exige para reconhecer um arquivo como plugin?

Um bloco de comentário no topo do arquivo principal com, no mínimo, a linha Plugin Name:. Sem esse cabeçalho, o WordPress simplesmente não lista o arquivo em Plugins. As demais linhas (Description, Version, Author, License, Text Domain) são recomendadas e alimentam a tela de plugins e a internacionalização.

Para que serve o if ( ! defined( 'ABSPATH' ) ) exit;?

É uma guarda de segurança. Se alguém acessar o arquivo PHP do plugin diretamente pela URL (sem passar pelo WordPress), a constante ABSPATH não estará definida e o script encerra na hora, sem executar nada. É uma linha que deve estar no topo de praticamente todo arquivo PHP de um plugin ou tema. Veja mais em segurança no código.

Qual a diferença entre desativar e desinstalar um plugin?

Desativar apenas para a execução do plugin — o código e os dados (opções, tabelas, posts) continuam no banco. Isso dispara o register_deactivation_hook(), ideal para limpar agendamentos de cron. Desinstalar remove o plugin de vez e é o momento de apagar dados que ele criou — feito no arquivo uninstall.php ou via register_uninstall_hook(). Não apague dados na desativação: o usuário pode só estar testando outro plugin.

Preciso prefixar funções mesmo em um plugin pequeno?

Sim. O WordPress carrega todos os plugins no mesmo escopo global. Se o seu plugin declarar uma função get_data() e outro plugin (ou o tema) declarar a mesma, o PHP encerra com um erro fatal de função redeclarada. Prefixar tudo — funções, opções, hooks personalizados e nomes de classe — com algo único (ex.: dwp_ ou um namespace) evita essas colisões. É barato fazer e caro de corrigir depois.

Quando devo usar mu-plugins em vez de um plugin normal?

Os must-use plugins ficam em wp-content/mu-plugins/, são carregados sempre e não podem ser desativados pelo painel. Use-os para código crítico de infraestrutura que nunca deve ser desligado por engano (regras de uma rede multisite, configurações forçadas de um cliente). A contrapartida: não têm hooks de ativação/desativação e não aparecem na lista normal de plugins. Para a maioria dos casos, um plugin comum é a escolha certa.

Referências oficiais

  1. WordPress.org — Plugin Handbook
  2. WordPress.org — Header Requirements
  3. WordPress.org — register_activation_hook()
  4. WordPress.org — Coding Standards
Tem alguma dúvida? Ficarei feliz em ajudar. Clique Aqui