
🔧 Como criar um modelo para um tipo de publicação personalizado no WordPress
Adicionou um tipo de publicação personalizado ao seu site, por exemplo «Promoções», «Portefólio» ou «Testemunhos». Tudo funciona: as publicações são criadas, os campos meta são preenchidos. Mas quando abre uma dessas publicações no front-end, ela parece uma publicação de blogue normal. O mesmo layout, as mesmas barras laterais, nenhuma diferença. No entanto, criou um tipo de publicação personalizado precisamente para que o conteúdo fosse apresentado de forma diferente.
O problema é que o WordPress renderiza qualquer publicação personalizada através do single.php por predefinição, o modelo universal para todas as publicações individuais. Para obter um layout único para um tipo específico, precisa do seu próprio ficheiro de modelo. E acaba por ser surpreendentemente fácil.
Abaixo está uma análise passo a passo: desde a hierarquia de modelos até dois métodos de criação (via um ficheiro de tema e via o filtro template_include), com exemplos de código funcionais.
💡 Visão geral rápida:
- Compreender como o WordPress procura um modelo para um tipo de publicação personalizado e a prioridade do
single-{post_type}.php - Copiar o
single.phpdo seu tema, renomeá-lo para o seu CPT e personalizá-lo - Explorar um método alternativo via o filtro
template_include(útil se não quiser mexer no tema) - Criar o próprio tipo de publicação personalizado usando o plugin Custom Post Type UI, de forma rápida e sem código
1. Como o WordPress escolhe um modelo para um tipo de publicação personalizado
A hierarquia de modelos do WordPress é uma cadeia de ficheiros que o núcleo verifica para encontrar o modelo certo para renderizar uma página. Para publicações padrão, a cadeia é longa: single-post.php → single.php → singular.php → index.php. Para tipos de publicação personalizados é mais curta, mas a lógica é a mesma.
Quando um visitante abre uma publicação personalizada do tipo aktsii, o WordPress verifica os ficheiros por esta ordem:
single-aktsii.php, o modelo específico para este tipo de publicação personalizadosingle.php, o modelo genérico de publicação individualsingular.php, o modelo para qualquer conteúdo singular (publicação, página, CPT)index.php, o recurso final de contingência
O primeiro ficheiro encontrado na cadeia é o usado para a renderização. Se o single-aktsii.php existir, o WordPress seleciona-o e para. Se não for encontrado, o núcleo avança para o single.php. É exatamente por isso que o seu tipo de publicação personalizado se parece com uma publicação normal: não existe um ficheiro single-aktsii.php, por isso o núcleo recorre ao single.php genérico.
A solução decorre diretamente daqui: crie o single-{post_type}.php e o WordPress seleciona-o automaticamente.
2. Criar um ficheiro de modelo: copiar o single.php e renomeá-lo
Esta é a abordagem mais simples e fiável. Funciona com qualquer tema clássico e não requer plugins nem filtros.
Passo 1: encontre o single.php do seu tema. Ele está na raiz da pasta do tema: /wp-content/themes/your-theme/single.php. Se o tema usar FSE (Full Site Editing) e for construído em blocos, este ficheiro pode não existir e o método do filtro (template_include) será mais conveniente (secção 4).
Passo 2: copie e renomeie. Copie o single.php e nomeie-o seguindo o padrão single-{slug}.php: substitua {slug} pelo slug do seu tipo de publicação personalizado (o especificado durante o registo, em caracteres latinos). Por exemplo, para um tipo com o slug aktsii:
1 single-aktsii.php
Para um tipo com o slug portfolio, o ficheiro chamar-se-ia single-portfolio.php. Para testimonials torna-se single-testimonials.php. Importante: o slug deve corresponder ao especificado no parâmetro 'rewrite' => array('slug' => '...') durante o registo.
Passo 3: coloque o ficheiro de volta na pasta do tema. O WordPress irá selecioná-lo automaticamente para todas as publicações deste tipo. Não é necessária configuração adicional; a hierarquia de modelos trata disso automaticamente.
Passo 4: verifique. Abra qualquer publicação do tipo personalizado no front-end. Se vir a mesma página de antes, verifique o nome do ficheiro (maiúsculas/minúsculas, hífens em vez de underscores) e limpe a cache. Se o ficheiro foi criado num tema filho e o tema pai também contiver single-{post_type}.php, o tema filho tem prioridade.
3. Personalizar o conteúdo do modelo
O single.php copiado ainda é idêntico ao original; simplesmente renderiza o mesmo layout genérico. Agora preenchemo-lo com conteúdo específico do tipo de publicação personalizado.
3.1. Estrutura básica: exibir campos personalizados
Suponha que o tipo de publicação personalizado aktsii tem os campos aktsiya_data_start, aktsiya_data_end e aktsiya_skidka (criados via ACF, Meta Box ou manualmente). Aqui está um modelo mínimo que os exibe:
1 <?php 2 /** 3 * Template for custom type "Promotions" (single-aktsii.php) 4 */ 5 6 get_header(); 7 ?> 8 9 <main id="main" class="site-main" role="main"> 10 11 <?php while ( have_posts() ) : the_post(); ?> 12 13 <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> 14 15 <header class="entry-header"> 16 <?php the_title( '<h1 class="entry-title">', '</h1>' ); ?> 17 </header> 18 19 <?php if ( has_post_thumbnail() ) : ?> 20 <div class="post-thumbnail"> 21 <?php the_post_thumbnail( 'large' ); ?> 22 </div> 23 <?php endif; ?> 24 25 <div class="entry-content"> 26 <?php the_content(); ?> 27 28 <div class="custom-fields"> 29 <?php 30 $data_start = get_post_meta( get_the_ID(), 'aktsiya_data_start', true ); 31 $data_end = get_post_meta( get_the_ID(), 'aktsiya_data_end', true ); 32 $skidka = get_post_meta( get_the_ID(), 'aktsiya_skidka', true ); 33 34 if ( $data_start ) { 35 echo '<p><strong>Start Date:</strong> ' . esc_html( $data_start ) . '</p>'; 36 } 37 if ( $data_end ) { 38 echo '<p><strong>End Date:</strong> ' . esc_html( $data_end ) . '</p>'; 39 } 40 if ( $skidka ) { 41 echo '<p><strong>Discount:</strong> ' . esc_html( $skidka ) . '%</p>'; 42 } 43 ?> 44 </div> 45 </div> 46 47 </article> 48 49 <?php 50 if ( comments_open() || get_comments_number() ) : 51 comments_template(); 52 endif; 53 ?> 54 55 <?php endwhile; ?> 56 57 </main> 58 59 <?php 60 get_sidebar(); 61 get_footer();
Este é um modelo totalmente funcional que pode colocar no seu tema tal como está. Exibe o título, a imagem destacada, o conteúdo e três campos personalizados num bloco separado.
3.2. O que mais pode fazer com o modelo
A partir daqui, as possibilidades de personalização são virtualmente ilimitadas:
- Remover a barra lateral: simplesmente remova a chamada
get_sidebar(). - Alterar o wrapper HTML: substitua
<article>por uma<div>com a classe de que precisa, adicione a sua própria grelha. - Chamar uma parte de modelo específica: por exemplo,
get_template_part( 'template-parts/content', 'aktsii' )e mantenha a lógica num ficheiro separado. - Carregar estilos personalizados: via
wp_enqueue_style()dentro dofunctions.phpcom uma verificaçãois_singular( 'aktsii' ).
Uma nota importante: se o tema for atualizado, um ficheiro no tema pai pode ser sobrescrito. Portanto, trabalhe num tema filho ou use o método do filtro da próxima secção.
4. Abordagem alternativa: o filtro template_include
Se preferir não modificar ficheiros do tema (ou se o tema for baseado em blocos e não tiver um single.php clássico), pode atribuir um modelo via o hook template_include. Ele é acionado antes de o WordPress incluir o ficheiro de modelo e permite-lhe substituir o caminho.
Desvantagem: terá de armazenar o ficheiro de modelo num plugin ou num tema filho, e o código deve apontar para o caminho correto. Vantagem: a lógica não se perde quando o tema pai é atualizado.
4.1. Exemplo: um CPT, um modelo
Adicione isto ao functions.php do tema filho (ou a um MU-plugin):
1 add_filter( 'template_include', 'techblog_cpt_template', 99 ); 2 3 function techblog_cpt_template( $template ) { 4 if ( is_singular( 'aktsii' ) ) { 5 $custom_template = get_stylesheet_directory() . '/single-aktsii.php'; 6 if ( file_exists( $custom_template ) ) { 7 return $custom_template; 8 } 9 } 10 return $template; 11 }
O código verifica se a página atual pertence ao tipo de publicação personalizado aktsii. Se sim, procura o ficheiro single-aktsii.php na pasta do tema filho (get_stylesheet_directory()) e devolve-o. Se o ficheiro não for encontrado, devolve o $template predefinido inalterado.
4.2. Exemplo: vários CPTs com um único manipulador
Se tiver vários tipos de publicação personalizados, é conveniente consolidar a lógica num só filtro:
1 add_filter( 'template_include', 'techblog_cpt_templates', 99 ); 2 3 function techblog_cpt_templates( $template ) { 4 $cpt_templates = array( 5 'aktsii' => 'single-aktsii.php', 6 'portfolio' => 'single-portfolio.php', 7 'testimonials' => 'single-testimonials.php', 8 ); 9 10 foreach ( $cpt_templates as $cpt => $template_file ) { 11 if ( is_singular( $cpt ) ) { 12 $custom_template = get_stylesheet_directory() . '/' . $template_file; 13 if ( file_exists( $custom_template ) ) { 14 return $custom_template; 15 } 16 } 17 } 18 19 return $template; 20 }
Agora cada CPT recebe o seu próprio modelo e toda a lógica reside numa única função.
4.3. Armazenar modelos num plugin
Se distribuir o tipo de publicação personalizado como um plugin (em vez de como parte de um tema), faz sentido armazenar o modelo na pasta do plugin. Nesse caso, especifique o caminho via plugin_dir_path( __FILE__ ):
1 add_filter( 'template_include', 'myplugin_cpt_template', 99 ); 2 3 function myplugin_cpt_template( $template ) { 4 if ( is_singular( 'aktsii' ) ) { 5 $custom_template = plugin_dir_path( __FILE__ ) . 'templates/single-aktsii.php'; 6 if ( file_exists( $custom_template ) ) { 7 return $custom_template; 8 } 9 } 10 return $template; 11 }
Este padrão é usado por muitos plugins populares (WooCommerce, Easy Digital Downloads, The Events Calendar): eles incluem modelos internamente e carregam-nos via o filtro.
5. Criar o tipo de publicação personalizado
Temos o modelo pronto, mas para sermos completos, algumas palavras sobre de onde vem o próprio tipo de publicação personalizado.
5.1. Registo via código
Um registo mínimo de CPT no functions.php ou num MU-plugin:
1 add_action( 'init', 'techblog_register_cpt_aktsii' ); 2 3 function techblog_register_cpt_aktsii() { 4 $labels = array( 5 'name' => 'Promotions', 6 'singular_name' => 'Promotion', 7 'menu_name' => 'Promotions', 8 ); 9 10 $args = array( 11 'labels' => $labels, 12 'public' => true, 13 'has_archive' => true, 14 'supports' => array( 'title', 'editor', 'thumbnail' ), 15 'rewrite' => array( 'slug' => 'aktsii' ), 16 'show_in_rest' => true, 17 ); 18 19 register_post_type( 'aktsii', $args ); 20 }
O detalhe chave aqui é que o parâmetro 'rewrite' => array( 'slug' => 'aktsii' ) define o slug usado tanto no URL como no nome do ficheiro de modelo. Se o slug for aktsii, o ficheiro de modelo deve chamar-se single-aktsii.php.
5.2. Usar o plugin Custom Post Type UI
Se preferir não editar o functions.php, pode criar um CPT visualmente usando o plugin gratuito Custom Post Type UI no WordPress.org. Após a instalação:
- No painel de administração, vá a CPT UI → Add/Edit Post Types
- Preencha os campos: Post Type Slug (caracteres latinos), Plural Label, Singular Label
- No separador Settings, selecione as funcionalidades do editor de que precisa (título, editor, miniatura)
- Clique em Add Post Type
O plugin gera o código PHP de registo, que pode exportar e colar no functions.php. Isto é conveniente se mais tarde quiser remover a dependência do plugin. O slug que especificou no CPT UI é o mesmo que vai para o nome do ficheiro de modelo.
⁉️🤔 Perguntas frequentes
O que devo fazer se o modelo não for selecionado após criar o ficheiro?
Reconstrua os permalinks: vá a Settings → Permalinks e clique em «Save Changes» (não precisa de alterar nada). O WordPress reconstruirá as suas regras de roteamento. Se isso não ajudar, verifique o nome do ficheiro: o slug do tipo de publicação personalizado e o nome do ficheiro devem corresponder (maiúsculas/minúsculas, hífens e underscores). Como terceiro passo, limpe a cache do seu plugin de cache, se tiver um instalado. Os permalinks devem ser reconstruídos após registar qualquer novo tipo de publicação personalizado, não apenas quando encontra problemas de modelo. Esta é uma prática padrão: vá a Settings → Permalinks → Save e os novos URLs começam a funcionar imediatamente.
Posso usar um modelo para vários tipos de publicação personalizados?
Sim, de duas formas. Primeiro, crie um ficheiro físico
single-aktsii.phpe, para o segundo tipo (digamos,portfolio), copie-o comosingle-portfolio.php. Segundo, use o filtrotemplate_include(secção 4): no array$cpt_templates, aponte tipos diferentes para o mesmo ficheiro de modelo. Na prática, porém, CPTs diferentes quase sempre têm layouts diferentes; copiar e editar é mais simples do que construir lógica condicional dentro de um único modelo. Se tiver realmente muitos tipos com lógica idêntica, crie umsingle-cpt.phppartilhado, verifiqueget_post_type()dentro dele e inclua a parte de modelo correspondente viaget_template_part( 'template-parts/content', get_post_type() ). Esta é uma abordagem limpa e escalável.
Preciso de criar o archive-{post_type}.php** para a página de arquivo?**
É recomendado, mas não obrigatório. Sem ele, o WordPress usa o
archive.phpou oindex.php. Se o CPT tiver'has_archive' => truee o arquivo abrir em/aktsii/, mas não existir um ficheiroarchive-aktsii.php, será usado oarchive.phpgenérico. Criar um modelo de arquivo separado faz sentido quando a grelha de publicações, o layout de colunas ou a barra lateral devem diferir do arquivo do blogue.
Isto funciona com temas de blocos (FSE)?
Em temas de blocos, os ficheiros de modelo PHP clássicos não são a abordagem principal. No entanto, o filtro
template_include(secção 4) funciona também no FSE: pode colocar osingle-aktsii.phpnum tema filho ou plugin e incluí-lo via o filtro. Alternativamente, no Editor de Site pode criar um modelo para um tipo de publicação personalizado específico através da interface: Appearance → Editor → Templates → Add New Template → Single Item: Aktsii. O WordPress irá guardá-lo como um modelo HTML na base de dados e funcionará sem quaisquer ficheiros no tema.
O que escolher em 2026: ficheiro ou filtro?
Uma matriz de decisão rápida para escolher a abordagem:
Cenário | O que usar |
|---|---|
Tema clássico, um ou dois CPTs | Ficheiro |
Tema filho, está a adicionar o CPT | Ficheiro no tema filho, sobrevive a atualizações do tema pai |
Tema de blocos (FSE), CPT via um plugin | Filtro |
CPT distribuído como um plugin | Filtro + modelo dentro da pasta do plugin |
Muitos CPTs com uma estrutura semelhante | Filtro + |
Na prática, no techblog.sdstudio.top usamos mais frequentemente uma combinação: registamos o CPT via código num MU-plugin e colocamos os modelos como ficheiros num tema filho. Isto proporciona seleção automática sem filtros extra e as atualizações do tema pai não quebram nada.
Se está a começar a aprender sobre tipos de publicação personalizados, comece com o ficheiro single-{post_type}.php. Demora cinco minutos e produz resultados instantâneos. Quando sentir que a abordagem baseada em ficheiros já não é suficiente (precisa de carregar modelos de um plugin ou trocá-los dinamicamente), mude para o template_include. Ambos os métodos são totalmente legítimos e suportados pelo núcleo do WordPress.



