
🛠 Taxonomias exclusivas no WordPress: como substituir caixas de seleção por botões de rádio
Por predefinição, o WordPress permite atribuir a uma publicação quantos termos de uma única taxonomia quiser. Caixas de seleção na barra lateral e está pronto. Mas e se o cliente precisar que o editor selecione exatamente uma opção? Por exemplo, «Tipo de projeto»: caso de estudo, página de destino ou loja online. Três opções, e ter duas delas em conjunto não faz sentido.
Não existe nenhum interruptor incorporado para «tornar a taxonomia exclusiva» no WordPress. Um ticket no Trac está parado desde 2010, sem progresso. Mas a tarefa pode ser resolvida com código, sem plugins ou dependências extra.
No final deste artigo, irá transformar a caixa meta padrão com caixas de seleção num painel com botões de rádio: exatamente um termo por publicação, menos erros do editor.
💡 Resumo rápido:
- Registe uma taxonomia com o parâmetro meta_box_cb para que a caixa meta padrão não apareça.
- No hook add_meta_boxes, crie o seu próprio bloco com botões de rádio.
- Use save_post para escrever o termo selecionado na base de dados.
- O código completo pode ser copiado para o ficheiro functions.php do tema filho e funciona de imediato.
O que são taxonomias e porque é que a exclusividade é importante
Uma taxonomia no WordPress é um mecanismo para agrupar publicações. As «Categorias» e «Etiquetas» padrão também são taxonomias. Uma taxonomia personalizada é criada para uma tarefa específica: «Tipo de projeto» para um portefólio, «Região» para um diretório de filiais, «Tipo de serviço» para uma lista de preços.
As categorias incorporadas funcionam como uma taxonomia exclusiva: uma publicação pertence exatamente a uma categoria, a menos que use plugins de extensão. A hierarquia «pai → filho» sugere a lógica de seleção ao editor.
No entanto, qualquer taxonomia personalizada registada através de register_taxonomy() é não exclusiva por predefinição. A interface consiste em caixas de seleção ou um campo com preenchimento automático. Para etiquetas e atributos de produtos, isto está correto. Mas quando cada publicação deve ter exatamente um termo, as caixas de seleção tornam-se uma fonte de erros.
A solução: oculte a caixa meta padrão e renderize a sua própria, com botões de rádio e controlo rigoroso. Isto não é uma solução de recurso, mas sim uma API documentada do WordPress, apenas distribuída por vários passos.
Passo 1: registar uma taxonomia personalizada
A base é a função register_taxonomy(). O código é adicionado ao functions.php do tema filho ou através do plugin Code Snippets. Vamos criar uma taxonomia project_type para publicações padrão:
1 function sd_register_project_type_taxonomy() { 2 register_taxonomy( 3 'project_type', 4 'post', 5 array( 6 'label' => __( 'Project Type', 'textdomain' ), 7 'public' => true, 8 'show_in_rest' => true, 9 'hierarchical' => true, 10 'show_in_quick_edit' => false, 11 'meta_box_cb' => false, 12 ) 13 ); 14 } 15 add_action( 'init', 'sd_register_project_type_taxonomy' );
Parâmetros chave:
hierarchical => trueativa uma estrutura em árvore, como as categorias. Os termos são organizados hierarquicamente: «Design → Página de destino», «Desenvolvimento → Loja online».show_in_rest => truetorna a taxonomia disponível na API REST e no editor de blocos. Sem isto, o Gutenberg não verá a caixa meta.meta_box_cb => falseeshow_in_quick_edit => falseremovem completamente a interface padrão de seleção de termos.
Depois de guardar o código, a taxonomia project_type apareceu no menu «Publicações». Os termos são adicionados através de «Publicações → Tipo de projeto» com uma interface padrão, como para as categorias.
Passo 2: ocultar a caixa meta padrão
Este passo já foi, na verdade, realizado com os parâmetros meta_box_cb e show_in_quick_edit no passo 1. Para recapitular:
meta_box_cb => falseremove a caixa meta da página de edição da publicação.show_in_quick_edit => falseoculta a taxonomia dos painéis de edição rápida e em massa.
Sem eles, o WordPress adiciona uma interface padrão: para taxonomias hierárquicas, caixas de seleção de categorias; para as não hierárquicas, um campo de etiqueta com preenchimento automático.

Os termos são preenchidos através de uma página de gestão separada:

Passo 3: criar uma caixa meta personalizada com botões de rádio
Registe a sua própria caixa meta através do hook add_meta_boxes. Adicione ao functions.php:
1 add_action( 'add_meta_boxes', 'sd_add_project_type_meta_box' ); 2 3 function sd_add_project_type_meta_box() { 4 add_meta_box( 5 'project_type_box', 6 __( 'Project Type', 'textdomain' ), 7 'sd_render_project_type_meta_box', 8 'post', 9 'side', 10 'default' 11 ); 12 }
Parâmetros de add_meta_box():
project_type_box: ID interno (arbitrário, mas único).'Project Type': título no painel de administração.sd_render_project_type_meta_box: função de renderização.'post': tipo de publicação; pode ser um array para vários CPT.'side': barra lateral. Alternativas:'normal','advanced'.
A função que renderiza os botões de rádio:
1 function sd_render_project_type_meta_box( $post ) { 2 $terms = get_terms( array( 3 'taxonomy' => 'project_type', 4 'hide_empty' => false, 5 ) ); 6 7 if ( empty( $terms ) || is_wp_error( $terms ) ) { 8 echo '<p>First, add terms on the “Project Type” page.</p>'; 9 return; 10 } 11 12 $current_terms = get_the_terms( $post->ID, 'project_type' ); 13 $current_id = ( ! empty( $current_terms ) && ! is_wp_error( $current_terms ) ) 14 ? $current_terms[0]->term_id 15 : 0; 16 17 foreach ( $terms as $term ) : ?> 18 <label style="display:block;margin-bottom:4px;"> 19 <input type="radio" 20 name="project_type_term" 21 value="<?php echo esc_attr( $term->term_id ); ?>" 22 <?php checked( $current_id, $term->term_id ); ?>> 23 <?php echo esc_html( $term->name ); ?> 24 </label> 25 <?php endforeach; 26 }
O que é importante aqui:
get_terms()comhide_empty => falsedevolve todos os termos, incluindo os não utilizados.get_the_terms()devolve um array; usamos o primeiro elemento[0], uma vez que a lógica garante que não há mais do que um termo.checked()é uma função incorporada do WordPress que produzchecked="checked"quando há uma correspondência.esc_attr()eesc_html()são escapes obrigatórios.
O resultado é um bloco limpo com botões de rádio:

Sem caixas de seleção, sem forma de selecionar duas opções.
Passo 4: guardar o termo quando a publicação é guardada
Sem este passo, a caixa meta é puramente decorativa. Usamos o hook save_post:
1 add_action( 'save_post', 'sd_save_project_type_term' ); 2 3 function sd_save_project_type_term( $post_id ) { 4 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { 5 return; 6 } 7 8 if ( ! current_user_can( 'edit_post', $post_id ) ) { 9 return; 10 } 11 12 if ( isset( $_POST['project_type_term'] ) ) { 13 $term_id = absint( $_POST['project_type_term'] ); 14 wp_set_object_terms( $post_id, $term_id, 'project_type' ); 15 } 16 }
Detalhes:
DOING_AUTOSAVE: ignoramos os autosaves. Sem esta verificação, o termo é sobrescrito em segundo plano a cada 60 segundos.current_user_can( 'edit_post', $post_id ): controlo básico de permissões.absint()converte o valor para um número inteiro positivo, mais seguro do que(int) sanitize_text_field().wp_set_object_terms()com um único ID (não um array) escreve exatamente um termo, removendo associações anteriores.
Pronto. Guarde a publicação e a seleção do botão de rádio será fixada. Quando a reabrir, o termo selecionado estará destacado.
Código completo para copiar
Todos os quatro passos num único fragmento. Adicione ao functions.php do seu tema filho ou através do Code Snippets:
1 /** 2 * Exclusive taxonomy "Project Type" — one term per post. 3 * Add to child theme's functions.php. 4 */ 5 function sd_register_project_type_taxonomy() { 6 register_taxonomy( 7 'project_type', 8 'post', 9 array( 10 'label' => __( 'Project Type', 'textdomain' ), 11 'public' => true, 12 'show_in_rest' => true, 13 'hierarchical' => true, 14 'show_in_quick_edit' => false, 15 'meta_box_cb' => false, 16 ) 17 ); 18 } 19 add_action( 'init', 'sd_register_project_type_taxonomy' ); 20 21 add_action( 'add_meta_boxes', 'sd_add_project_type_meta_box' ); 22 23 function sd_add_project_type_meta_box() { 24 add_meta_box( 25 'project_type_box', 26 __( 'Project Type', 'textdomain' ), 27 'sd_render_project_type_meta_box', 28 'post', 29 'side', 30 'default' 31 ); 32 } 33 34 function sd_render_project_type_meta_box( $post ) { 35 $terms = get_terms( array( 36 'taxonomy' => 'project_type', 37 'hide_empty' => false, 38 ) ); 39 40 if ( empty( $terms ) || is_wp_error( $terms ) ) { 41 echo '<p>First, add terms on the “Project Type” page.</p>'; 42 return; 43 } 44 45 $current_terms = get_the_terms( $post->ID, 'project_type' ); 46 $current_id = ( ! empty( $current_terms ) && ! is_wp_error( $current_terms ) ) 47 ? $current_terms[0]->term_id 48 : 0; 49 50 foreach ( $terms as $term ) : ?> 51 <label style="display:block;margin-bottom:4px;"> 52 <input type="radio" 53 name="project_type_term" 54 value="<?php echo esc_attr( $term->term_id ); ?>" 55 <?php checked( $current_id, $term->term_id ); ?>> 56 <?php echo esc_html( $term->name ); ?> 57 </label> 58 <?php endforeach; 59 } 60 61 add_action( 'save_post', 'sd_save_project_type_term' ); 62 63 function sd_save_project_type_term( $post_id ) { 64 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { 65 return; 66 } 67 68 if ( ! current_user_can( 'edit_post', $post_id ) ) { 69 return; 70 } 71 72 if ( isset( $_POST['project_type_term'] ) ) { 73 $term_id = absint( $_POST['project_type_term'] ); 74 wp_set_object_terms( $post_id, $term_id, 'project_type' ); 75 } 76 }
⚠️ Faça uma cópia de segurança completa do site antes de colar. O código foi testado na versão atual do WordPress com o editor clássico. No Gutenberg, a caixa meta personalizada é exibida na barra lateral sem alterações.
Na prática, implementámos este fragmento em três projetos e funcionou em todos sem modificações. Se tiver um tipo de publicação hierárquico ou várias funções de editor, substitua 'post' pelo seu slug e verifique as permissões em save_post.
O Trac do WordPress tem o ticket #14877 aberto desde 2010 para suporte nativo a taxonomia exclusiva. Assim que um parâmetro 'exclusive' => true aparecer no núcleo, toda esta construção será reduzida a uma única linha. Até que o ticket tenha movimento, a abordagem dos botões de rádio continua a ser a solução principal.
E abaixo, um pequeno vídeo sobre o tema para que possa ver o processo em ação:
⁉️🤔 Perguntas frequentes
Isto funciona no Gutenberg?
Sim. O parâmetro
show_in_rest => trueao registar a taxonomia permite a compatibilidade com o editor de blocos. A caixa meta personalizada aparece na barra lateral do documento e os botões de rádio são exibidos e guardados corretamente.
Esta abordagem pode ser aplicada a tipos de publicação personalizados?
Sim. Substitua
'post'emregister_taxonomy()eadd_meta_box()pelo slug do seu CPT. O resto do código (nome da taxonomia, etiqueta, parâmetros) permanece igual. A abordagem funciona com qualquer tipo de publicação registado, incluindo os criados através de ACF ou Custom Post Type UI.
O que acontece se o editor não selecionar nenhum termo?
A publicação será guardada sem um termo atribuído; o
save_postsimplesmente não chamaráwp_set_object_terms(). Se a seleção obrigatória for crítica, adicione validação JavaScript na administração ou uma verificação através do hookpre_post_update.
Porque não usar o plugin Radio Buttons for Taxonomies?
Pode usar. O plugin resolve a tarefa sem código e tem mais de 100.000 instalações ativas. A desvantagem é mais uma dependência. Para um ou dois sites, o plugin justifica-se. Para agências e multisites, o código no tema dá controlo total sem atualizações extra e conflitos.
Como adiciono seleção hierárquica (pai → filho)?
As taxonomias hierárquicas (
hierarchical => true) obtêm automaticamente uma estrutura pai-filho. Para exibir a hierarquia na caixa meta personalizada, substituaget_terms()porwp_dropdown_categories()usando o parâmetro'taxonomy' => 'project_type'; a função produzirá um seletor com indentação.
Resumo final: quando vale a pena o esforço de escrever código
Uma taxonomia exclusiva não é necessária para todos os projetos. Se os editores compreendem a lógica do site e não cometem erros ao selecionar, as caixas de seleção padrão são suficientes. Mas quando o custo dos erros é alto (uma página de destino no portefólio marcada por engano como «loja online» e «caso de estudo»), meia hora de codificação compensa com a limpeza do conteúdo.
- Se tem um site e nenhum programador, instale o Radio Buttons for Taxonomies. Funciona sem código.
- Se é uma agência ou gere um multisite, copie o código acima para o seu tema base. Menos plugins, menos pontos de falha durante as atualizações.
- Se o seu site funciona em Gutenberg puro, considere se precisa mesmo de uma taxonomia. Talvez um campo ACF com botões de rádio seja suficiente: menos entidades, administração mais rápida.
Comece com um site de teste. Registe a taxonomia, adicione três termos e crie uma publicação; a interface funcionará de imediato. Escreva nos comentários para que tarefa usou uma taxonomia exclusiva.



