Back

Criando um Custom Post Type no WordPress

Criando um Custom Post Type no WordPress

O WordPress vem com Posts e Páginas, mas esses dois tipos de conteúdo não são suficientes quando um cliente precisa de um diretório de imóveis, uma lista de funcionários ou um arquivo de receitas. É aí que entra um custom post type do WordPress — uma estrutura de conteúdo de primeira classe que se encaixa perfeitamente no modelo de dados existente do WordPress sem precisar modificar os padrões.

Principais Pontos

  • Um custom post type (CPT) estende a tabela compartilhada wp_posts em vez de criar uma separada, fornecendo telas de administração, endpoints da REST API e roteamento de templates prontos para uso.
  • Sempre registre CPTs em um plugin, não em um tema, para que o conteúdo permaneça acessível independentemente de mudanças de tema.
  • Definir show_in_rest como true é necessário para suporte ao editor de blocos e exposição via REST API.
  • Limpe as regras de reescrita apenas na ativação do plugin — nunca em cada carregamento de página.

O Que É um Custom Post Type?

Um custom post type (CPT) é um tipo de conteúdo nomeado que você registra no WordPress. Apesar do nome, não é uma tabela de banco de dados separada. Todos os tipos de post — nativos e personalizados — compartilham a tabela wp_posts, diferenciados pela coluna post_type. Este é um modelo mental importante: você está estendendo uma estrutura existente, não criando uma paralela.

Os tipos de post padrão incluem post, page, attachment, revision e nav_menu_item. Quando você registra um CPT como property ou recipe, o WordPress o trata com a mesma consistência: telas de administração, endpoints da REST API, roteamento de URL e hierarquia de templates funcionam da mesma forma.

Custom post types ≠ custom fields. Um CPT define o tipo de conteúdo. Custom fields (adicionados via ACF ou a API de metadados) armazenam dados extras anexados a esse conteúdo. São preocupações separadas.

Registrando um Custom Post Type com register_post_type()

A forma canônica de criar um custom post type no WordPress é através da função register_post_type(), chamada no hook init.

Aqui está um exemplo limpo e funcional:

add_action( 'init', 'register_property_post_type' );

function register_property_post_type() {
    $labels = [
        'name'               => 'Properties',
        'singular_name'      => 'Property',
        'add_new_item'       => 'Add New Property',
        'edit_item'          => 'Edit Property',
        'not_found'          => 'No properties found.',
    ];

    $args = [
        'labels'       => $labels,
        'public'       => true,
        'has_archive'  => true,
        'supports'     => [ 'title', 'editor', 'thumbnail', 'excerpt' ],
        'rewrite'      => [ 'slug' => 'properties' ],
        'show_in_rest' => true,
    ];

    register_post_type( 'property', $args );
}

Principais Argumentos Explicados

  • public — Torna o CPT visível no painel administrativo e no front-end. Defina como false para tipos apenas internos.
  • labels — Controla todas as strings da interface no admin. Vale a pena preencher adequadamente para que os editores não fiquem confusos.
  • supports — Declara quais recursos do editor aparecem na tela de edição. Valores comuns: title, editor, thumbnail, excerpt, custom-fields.
  • has_archive — Habilita uma página de arquivo em /properties/. O WordPress procurará por um template archive-property.php correspondente (ou usará archive.php como fallback).
  • rewrite — Define o slug da URL. Posts individuais aparecerão em /properties/post-name/.
  • show_in_restDefina como true. Isso expõe o CPT via WordPress REST API e é necessário para que o editor de blocos funcione corretamente com seu tipo de post. Sem isso, o editor volta para a interface clássica.

Plugin vs. Tema: Onde o Código Deve Ficar?

Este é um ponto comum de confusão. Registre seu custom post type em um plugin, não em um tema.

Se o registro do seu CPT estiver no functions.php e o cliente trocar de tema, todo o conteúdo desse tipo se torna inacessível — não é deletado, mas fica invisível. Um plugin dedicado (mesmo um plugin de arquivo único) mantém o CPT ativo independentemente de mudanças de tema.

Não limpe as regras de reescrita em cada requisição. Chame flush_rewrite_rules() apenas uma vez — na ativação do plugin via register_activation_hook(). Limpar em cada init é um problema de performance.

Hierarquia de Templates para Custom Post Types

O WordPress procura por templates nesta ordem para uma entrada individual de CPT:

  1. single-{post-type}.php (ex: single-property.php)
  2. single.php
  3. singular.php
  4. index.php

Para arquivos, segue: archive-{post-type}.phparchive.phpindex.php.

Conclusão

Com register_post_type() corretamente vinculado ao init, show_in_rest habilitado e o registro vivendo em um plugin, você tem uma base sólida e portável. A partir daqui você pode adicionar taxonomias personalizadas, campos meta via ACF ou a API de metadados, e colunas personalizadas no admin — sem tocar em nada que quebraria quando o WordPress ou seu tema fossem atualizados.

Perguntas Frequentes

O conteúdo permanece na tabela wp_posts e não é deletado. No entanto, o WordPress não reconhece mais aquele tipo de post, então os posts se tornam invisíveis no admin e no front-end. Reativar o plugin restaura o acesso imediatamente. É por isso que o registro de CPT deve sempre estar em um plugin dedicado em vez de um tema.

Sim. Você pode chamar register_post_type() múltiplas vezes dentro do mesmo callback init ou usar callbacks separados vinculados ao init. Não há limite para o número de custom post types que um único plugin pode registrar, embora cada um deva ter um slug de tipo de post único com no máximo 20 caracteres.

Isso quase sempre significa que as regras de reescrita precisam ser limpas. Visite Configurações e depois Links Permanentes no admin do WordPress e clique em Salvar Alterações. Isso dispara uma limpeza de reescrita. Para plugins, chame flush_rewrite_rules() dentro de register_activation_hook() para que seja executado automaticamente na ativação. Nunca limpe em cada carregamento de página.

Não estritamente, mas ainda é recomendado. Definir show_in_rest como true expõe seu tipo de post através da WordPress REST API, o que é útil para configurações headless, integrações externas e compatibilidade futura. Se você algum dia mudar para o editor de blocos, ele já funcionará corretamente.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay