Crie blocos personalizados só com PHP. Adeus aos velhos shortcodes 🥳
Criar blocos Gutenberg significava React, Node.js e uma pipeline de compilação desde que o WordPress 5.0 introduziu o editor de blocos. Se suas habilidades são em PHP — como as minhas e as da maioria dos desenvolvedores WordPress — essa barreira manteve você à margem por quase uma década. O WordPress 7.0 muda isso. Os blocos somente em PHP permitem registrar um bloco Gutenberg totalmente funcional com um único arquivo PHP e a flag autoRegister.
Você escreve PHP. Você obtém um bloco. Sem tooling. Sem compilação. 🥳 Neste artigo você verá como os blocos somente em PHP funcionam, e vai acompanhar um exemplo do mundo real que substitui um shortcode clássico pelo seu equivalente em bloco.
O que são blocos somente em PHP?
Até agora, criar um bloco Gutenberg personalizado significava configurar uma toolchain JavaScript: npm install, um arquivo block.json, uma etapa de compilação com webpack.config.js ou @wordpress/scripts, e um componente edit.js escrito em JSX. Cada alteração exigia uma etapa de compilação antes de poder ser vista no editor. Para um desenvolvedor PHP que só quer registrar um bloco de exibição simples, esse custo sempre pareceu desproporcional à tarefa.
Os blocos somente em PHP eliminam tudo isso. Agora, em register_block_type() você só precisa passar 'autoRegister' => true, e o WordPress cuida de tudo no lado JavaScript automaticamente usando ServerSideRender. O bloco aparece no inseridor, renderiza uma prévia ao vivo na tela e gera os controles do Inspetor na barra lateral — tudo sem uma única linha de JavaScript da sua parte.
Os controles são gerados automaticamente com base no tipo de atributo:
| Tipo de atributo | Controle do Inspetor gerado |
|---|---|
string | Campo de texto |
integer / number | Campo numérico |
boolean | Toggle |
string + enum | Menu suspenso |
Os controles gerados automaticamente cobrem por ora apenas os quatro tipos acima. Qualquer coisa mais complexa, como seletores de imagem, uploads de mídia ou dados aninhados, ainda não é suportada e exigiria um bloco registrado com JavaScript. Os desenvolvedores também podem marcar atributos individuais com um papel local para sinalizá-los como estado interno; o WordPress os ignora ao construir os controles da barra lateral.
Os blocos somente em PHP estão disponíveis hoje no WordPress 7.0 sem dependências adicionais. Leia mais na nota oficial para desenvolvedores no Make WordPress Core.
Para quem é isso?
Agências menores e freelancers sem profundo conhecimento em JavaScript podem agora criar soluções para o editor de blocos que fazem uso pleno dos recursos nativos do WordPress sem tocar em uma pipeline de compilação. Se você quer criar blocos Gutenberg personalizados específicos para um tema — como caixas de autor, citações em destaque, depoimentos, banners CTA, avisos e elementos semelhantes — em vez de recorrer a shortcodes, os blocos somente em PHP ajudam a reduzir significativamente essa barreira.
Eles não substituem os blocos registrados com JavaScript quando você precisa de edição inline de texto rico, interface reativa em tempo real ou aninhamento de blocos internos — mas para uma grande classe de blocos de exibição estruturados, eles atingem o ponto certo.
O método antigo: shortcodes
Antes dos blocos somente em PHP, a abordagem prática do desenvolvedor PHP era um shortcode. Aqui está um shortcode simples de depoimento com três atributos: nome do autor, empresa, uma avaliação em estrelas, mais o conteúdo interno para o texto da avaliação:
function testimonial_shortcode( $atts, $content = '' ) {
$atts = shortcode_atts( [
'name' => '',
'company' => '',
'stars' => 5,
], $atts );
$stars_count = max( 1, min( 5, intval( $atts['stars'] ) ) );
$stars_html = str_repeat( '★', $stars_count )
. str_repeat( '☆', 5 - $stars_count );
return sprintf(
'<blockquote class="testimonial">
<p class="testimonial__stars">%s</p>
<p class="testimonial__body">%s</p>
<footer class="testimonial__attribution">
<strong>%s</strong>%s
</footer>
</blockquote>',
esc_html( $stars_html ),
wp_kses_post( $content ),
esc_html( $atts['name'] ),
$atts['company'] ? ', ' . esc_html( $atts['company'] ) : ''
);
}
add_shortcode( 'testimonial', 'testimonial_shortcode' );Uso:
[testimonial name="Sarah K." company="Acme Corp" stars="4"]
Saved us hours every week.
[/testimonial]Funciona... mas é só um shortcode 🤷🏻♂️
Aqui estão apenas alguns dos problemas com shortcodes:
- Invisível no editor. O autor vê
[testimonial name="Sarah K." ...]no editor, não o card renderizado. Não há prévia. - Não é descobrível. Você precisa saber que o shortcode existe e lembrar os nomes dos parâmetros. Nada o torna visível na interface.
- Sem controles de estilo nativos. Ajustar cor, espaçamento ou tipografia requer CSS personalizado ou atributos extras conectados manualmente.
- O conteúdo interno não é texto rico. O corpo da avaliação é passado como uma string simples em
$content— não uma área de texto rico editável.
Os shortcodes foram a ferramenta certa para sua época. O editor de blocos oferece algo melhor, mas tem sido difícil de aproveitar. O WordPress 7.0 oferece um atalho na forma de blocos somente em PHP.
Para ser claro: a forma correta e moderna de criar um bloco Gutenberg ainda é um bloco registrado com JavaScript com um componente edit completo. Os blocos somente em PHP são um caminho simplificado — deliberadamente limitado a blocos renderizados no servidor que não precisam de edição rica na tela. Eles não substituem os blocos JavaScript, mas são uma nova opção para casos de uso mais simples onde o custo de uma pipeline de compilação e componentes React não se justifica.
Uma opção mais simples: blocos somente em PHP
Vamos construir o mesmo depoimento como um bloco personalizado do WordPress só com PHP. A receita: register_block_type() com 'autoRegister' => true em supports, mais um render_callback.
Aqui está o código completo do bloco:
function my_plugin_register_testimonial_block() {
register_block_type(
'my-plugin/testimonial', // Block name: namespace/slug
array(
'title' => 'Testimonial', // Shown in the block inserter
'attributes' => array(
// string attributes generate a text input in the sidebar
'name' => array(
'type' => 'string',
'default' => '',
),
'company' => array(
'type' => 'string',
'default' => '',
),
// integer attributes generate a number input
'stars' => array(
'type' => 'integer',
'default' => 5,
),
'body' => array(
'type' => 'string',
'default' => '',
),
),
// render_callback is the PHP function that outputs the block's HTML
'render_callback' => function ( $attributes ) {
$stars_count = max( 1, min( 5, intval( $attributes['stars'] ) ) );
$stars_html = str_repeat( '★', $stars_count )
. str_repeat( '☆', 5 - $stars_count );
// Translatable string for screen readers — standard WordPress i18n, nothing extra needed
/* translators: %d: star rating out of 5 */
$stars_label = sprintf( __( '%d out of 5 stars', 'my-plugin' ), $stars_count );
return sprintf(
'<blockquote %s>
<p class="testimonial__stars" aria-label="%s">%s</p>
<p class="testimonial__body">%s</p>
<cite class="testimonial__attribution">
<strong>%s</strong>%s
</cite>
</blockquote>',
// Merges your class with editor-added colour, spacing, and typography styles
get_block_wrapper_attributes( array( 'class' => 'testimonial wp-block-quote' ) ),
esc_attr( $stars_label ),
esc_html( $stars_html ),
wp_kses_post( $attributes['body'] ),
esc_html( $attributes['name'] ),
$attributes['company'] ? ', ' . esc_html( $attributes['company'] ) : ''
);
},
'supports' => array(
// The key flag — tells WordPress to handle JS registration automatically
'autoRegister' => true,
// The rest unlock native colour, typography, and spacing panels in the sidebar
'color' => array(
'background' => true,
'text' => true,
),
'typography' => array(
'fontSize' => true,
),
'spacing' => array(
'padding' => true,
'margin' => true,
),
),
)
);
}
add_action( 'init', 'my_plugin_register_testimonial_block' );O resultado:

Algumas coisas a observar aqui. Primeiro, o conteúdo interno de um shortcode não tem um equivalente direto nos blocos somente em PHP. O corpo da avaliação torna-se um atributo string editado pelos controles do Inspetor na barra lateral — um campo de texto de linha única, não uma área de texto rico na tela. Para uma citação curta de depoimento isso está bem. Para textos mais longos você vai querer um bloco registrado com JavaScript com um componente RichText.
Segundo, get_block_wrapper_attributes() combina sua classe com o que o editor adiciona para cor, tipografia e espaçamento — assim os painéis de estilo nativos funcionam sem nenhuma conexão CSS extra. O render_callback recebe um array $attributes contendo apenas os valores definidos pelo usuário; sem parâmetro $content, porque o conteúdo interno não é suportado.
O que você ganha em relação à versão com shortcode:
- Prévia ao vivo na tela do editor. Sem mais sintaxe bruta de shortcode — o autor vê o card de depoimento renderizado enquanto edita.
- Controles gerados automaticamente. Nome, empresa, corpo (campos de texto) e estrelas (campo numérico) aparecem automaticamente nos controles do Inspetor na barra lateral.
- Painéis nativos de cor, fonte e espaçamento. Vêm de
supports— sem necessidade de CSS personalizado. - Descobrível. O bloco aparece no inseridor com seu nome, com um ícone.
Pronto para tradução desde o início
Há duas preocupações de tradução distintas ao trabalhar com blocos somente em PHP, e vale a pena ter clareza sobre qual é qual.
A primeira são as strings estáticas incorporadas no seu template PHP — rótulos, textos de botões, textos da interface. Estas são tratadas por __() e _e(), assim como em qualquer arquivo PHP do WordPress. No bloco acima, o rótulo das estrelas é um exemplo:
/* translators: %d: star rating out of 5 */
$stars_label = sprintf( __( '%d out of 5 stars', 'my-plugin' ), $stars_count );As ferramentas padrão do WordPress as detectam automaticamente. Nada extra é necessário.
A segunda preocupação é o conteúdo inserido pelo usuário armazenado como atributos do bloco — o corpo do depoimento, o nome do avaliador, a empresa. Este é o conteúdo que seus editores realmente digitam no bloco, e __() não o toca. Em um site multilíngue, esses valores de atributo precisam ser traduzidos para cada idioma separadamente, e isso não é algo que o WordPress gerencia sozinho.
Gato AI Translations for Polylang suporta blocos somente em PHP desde o início, da mesma forma que suporta Gutenberg, Bricks, Elementor e outros page builders. Nenhuma configuração adicional é necessária.
Todos os atributos do tipo string são automaticamente registrados para tradução. Se um campo específico não deve ser traduzido — uma referência interna, uma URL, um código numérico armazenado como string — você pode excluí-lo com um filtro.
Para o bloco de depoimento neste artigo, o nome do avaliador, a empresa e o texto do corpo são todos traduzidos automaticamente — sem configuração além da instalação do plugin.
O que os blocos somente em PHP (ainda) não podem fazer
As limitações atuais dos blocos somente em PHP:
- Sem blocos internos ou aninhamento. Você não pode inserir outros blocos dentro de um bloco somente em PHP.
- Sem edição de texto rico na tela. O componente
RichTextrequer JavaScript. Os controles de texto são renderizados apenas como campo de texto na barra lateral. - Campos string da barra lateral são de linha única. Um atributo
stringse torna umTextControl, não umTextareaControl— não ideal para textos mais longos. - Sem atributos de seletor de imagem ou mídia. O suporte a upload de imagem/arquivo está planejado para uma versão futura via Block Fields API.
- A prévia do editor tem um atraso de ida e volta. Alterações nos atributos disparam uma requisição à REST API para re-renderizar no servidor, então a prévia não atualiza instantaneamente.
Para blocos estruturados simples — depoimentos, CTAs, avisos, bios de autor, listagens de empresas — os blocos somente em PHP atingem o ponto certo. Para qualquer coisa que exija edição rica na tela, o registro com JavaScript continua sendo a ferramenta certa.
O que vem a seguir
Os blocos somente em PHP do WordPress 7.0 trazem o desenvolvimento de blocos ao alcance de qualquer desenvolvedor PHP. Um arquivo PHP, uma chamada a register_block_type(), e você tem um bloco Gutenberg totalmente funcional com controles na barra lateral, uma prévia ao vivo na tela e suporte a estilos nativos. Você escreve PHP. Você obtém um bloco. Sem tooling. Sem compilação. Sem JavaScript.
Se você está criando sites multilíngues, o Gato AI Translations funciona perfeitamente com blocos somente em PHP — seu conteúdo é traduzível desde o primeiro dia.
Pronto para ir além?
- Developing WordPress blocks without JSX or a build process — para desenvolvedores que querem adicionar JavaScript mínimo sem uma pipeline de compilação completa
- Beginner WordPress Developer course — uma base completa para o desenvolvimento de blocos