O desenvolvimento tradicional de temas WordPress depende da repetição de marcação de cabeçalho e rodapé em vários arquivos de template. Sempre que você atualiza um menu de navegação ou um elemento do rodapé, precisa localizar todos os arquivos de template que incluem essa marcação e fazer as alterações necessárias em vários lugares. Isso cria mais trabalho de manutenção e aumenta o risco de inconsistências em todo o site.
O Radicle traz o mecanismo de templates Blade, do Laravel, para o WordPress por meio da arquitetura baseada em componentes do Acorn. Em vez de espalhar marcação entre vários arquivos de template, você define componentes reutilizáveis uma única vez e os referencia em todo o seu tema. Quando precisar atualizar um elemento da interface, você modifica apenas um arquivo de componente, em vez de procurar a alteração em dezenas de templates.
Por que o desenvolvimento de templates no WordPress precisa de uma arquitetura baseada em componentes
O WordPress armazena templates dentro de uma estrutura de diretórios de tema, onde header.php e footer.php aparecem em todos os templates de página por meio das chamadas get_header() e get_footer(). Isso funciona para sites simples, mas começa a causar problemas quando projetos mais complexos precisam escalar.
Por exemplo, um site com tipos de post personalizados, landing pages e templates de marketing inclui a mesma marcação de navegação, estrutura de rodapé e elementos de barra lateral em cada arquivo de template. Isso exige que você procure em vários arquivos de template sempre que precisar adicionar um novo item de menu ou atualizar um formulário de contato no rodapé.
O Radicle organiza os templates Blade em resources/views/ com diretórios separados para layouts, components e blocks:
components. Este diretório inclui elementos de interface independentes, como títulos e botões.layouts. Aqui ficam os templates estruturais que definem a estrutura das páginas.blocks.Aqui você armazena templates de blocos que se integram ao Editor de Site do WordPress.
Essa organização cria uma fonte única de verdade para cada elemento da interface. Um componente x-heading define a marcação e o estilo do título em um único local. Assim, quando você usa esse componente em vários templates, o Blade referencia essa única definição. Como consequência, atualizar o componente atualiza todas as ocorrências em todo o site.
Como criar layouts principais que eliminam código duplicado
Em vez de duplicar a marcação da navegação e do rodapé, você pode usar a herança de templates para criar um layout principal que defina o shell do site.
Um layout começa com um arquivo de componente Blade em resources/views/components/. O arquivo layout.blade.php define a estrutura HTML que envolve o conteúdo da página. Isso inclui o doctype, a seção head com metatags e referências de assets, a estrutura de navegação e os elementos do rodapé. O elemento-chave em um layout é a variável $slot, que o Blade usa como ponto de inserção de conteúdo.
<html>
<head>
<title>{{ $title ?? 'My Site' }}</title>
</head>
<body>
<nav>
<!-- Navigation markup -->
</nav>
<main>
{{ $slot }}
</main>
<footer>
<!-- Footer markup -->
</footer>
</body>
</html>
Child templates estendem esse layout usando a sintaxe de componentes do Blade. Um template de página envolve seu conteúdo dentro das tags do componente x-layout. O Blade processa isso renderizando o componente de layout e inserindo o conteúdo do child templates onde aparece a variável $slot.
<x-layout>
<h1>Page Title</h1>
<p>Page content goes here.</p>
</x-layout>
Slots nomeados fornecem pontos adicionais de inserção para conteúdo dinâmico, como títulos de página. Em vez de aceitar apenas um slot padrão, você define slots específicos com nomes O componente x-slot com um atributo name passa o conteúdo para esses locais designados:
<x-layout>
<x-slot name="title">
Custom Page Title
</x-slot>
<h1>Page Heading</h1>
<p>Page content.</p>
</x-layout>
O componente de layout acessa os slots nomeados por meio de variáveis que correspondem aos nomes dos slots. Isso permite inserir conteúdo em vários pontos do layout a partir de um único child template.
Criando componentes de interface reutilizáveis para padrões de design consistentes
Os componentes Blade centralizam estilo e marcação para elementos comuns da interface.
Em vez de escrever marcação de botão com classes do Tailwind em cada template, você cria um componente de botão que encapsula essa marcação. O componente aceita props para personalização, mantendo um estilo base consistente.
O uso do componente x-heading com outros componentes de tipografia é um bom exemplo disso. Ele aceita uma propriedade level que determina o elemento HTML (h1, h2, h3) e uma propriedade size que controla a escala visual. O componente mapeia essas propriedades para as classes Tailwind internamente, o que mantém os detalhes da implementação separados.
<x-heading level="h1" size="3xl">
Main Page Title
</x-heading>
<x-heading level="h2" size="2xl">
Section Heading
</x-heading>
O arquivo do componente em resources/views/components/heading.blade.php define a lógica de marcação e estilo usando a diretiva @props do BBlade para declarar propriedades aceitas e seus valores padrão. Cada componente constrói o elemento HTML apropriado com classes baseadas nos valores das props.
Um componente x-link segue o mesmo padrão, com suporte a variants para diferentes estilos de link. A prop variant alterna entre apresentações padrão, botão e sem estilo.
Componentes de interface como x-button permitem aplicar o mesmo conceito a elementos interativos. O componente de botão suporta props size e variant para diferentes estilos. Quando combinado com um framework como Alpine.js por meio do componente x-modal, você pode lidar com interações sem espalhar JavaScript pelos templates:
<x-button variant="primary" @click="showModal = true">
Open Modal
</x-button>
<x-modal x-show="showModal">
<p>Modal content</p>
</x-modal>
As props funcionam bem para strings, booleanos e outros dados simples. Slots são mais adequados para conteúdo complexo que inclui marcação. Por exemplo, o componente de modal usa um slot padrão para receber todo o conteúdo do modal em vez de passar HTML por meio de uma prop.
Conectando dados do WordPress aos templates Blade com view composers
Os view composers permitem agregar dados de várias fontes antes de renderizar um template. Nesse caso, você cria uma classe composer que cuida da recuperação e transformação dos dados em vez de consultar posts diretamente nos templates. Assim, o template recebe dados estruturados prontos para exibição.
O modelo Post do Radicle simplifica o trabalho com dados de posts do WordPress usando alguns métodos:
title()retorna o título do post.- O método
content()recupera o conteúdo filtrado do post. excerpt()aceita uma contagem de palavras e gera um resumo.permalink()retorna o URL do post.
Para imagens em destaque, hasThumbnail() verifica se existe uma imagem e thumbnail() recupera o HTML da imagem com um tamanho especificado:
$post = Post::find(123);
echo $post->title();
echo $post->excerpt(30);
if ($post->hasThumbnail()) {
echo $post->thumbnail('large');
}
As classes de view composer ficam em app/View/Composers/ e estendem RootsAcornViewComposer. A classe define a quais views ela se aplica por meio da propriedade estática protegida $views, que aceita um array com nomes de templates. Para um composer da página inicial, você especifica 'front-page' para direcionar o template front-page.blade.php:
namespace AppViewComposers;
use AppModelsPost;
use RootsAcornViewComposer;
class FrontPage extends Composer
{
protected static $views = ['front-page'];
public function with()
{
return [
'recentPosts' => Post::recent(6)->get(),
'totalPosts' => Post::published()->count(),
];
}
}
O método with() retorna um array em que as chaves se tornam nomes de variáveis no template. Os valores podem ser coleções do Eloquent, modelos individuais ou qualquer estrutura de dados. Independentemente disso, esse método é executado antes que qualquer template renderize e prepare os dados.
O template front-page.blade.php acessa essas variáveis diretamente. A diretiva @foreach do Blade percorre os posts, e cada iteração permite acessar os métodos do modeloPost:
<div class="posts-grid">
@foreach ($recentPosts as $post)
<article>
@if ($post->hasThumbnail())
<img src="{{ $post->thumbnail('medium') }}" alt="{{ $post->title() }}">
@endif
<h2>
<a href="{{ $post->permalink() }}">{{ $post->title() }}</a>
</h2>
<p>{{ $post->excerpt(20) }}</p>
</article>
@endforeach
</div>
<p>Total posts: {{ $totalPosts }}</p>
Nesse padrão, o composer cuida das consultas e da transformação dos dados, enquanto o template se concentra na marcação e na lógica de exibição. Quando você precisar modificar a estrutura dos dados ou adicionar novas consultas, basta atualizar o composer sem precisar alterar arquivos de template.
Criando blocos para o Editor de Site do WordPress com renderização Blade
O Radicle usa renderização no lado do servidor para Blocks do Editor de Site por meio de templates Blade. O componente JavaScript do editor controla a interface do Block no painel administrativo do WordPress, enquanto o template Blade gera a saída no frontend.
Isso permite construir interfaces de blocos com React, por exemplo, enquanto o HTML final é renderizado com Blade.
O comando wp acorn make:block gera três arquivos para cada bloco:
- Um arquivo de classe PHP em
app/Blocks/que gerencia a lógica no servidor. - O componente JSX em
resources/js/editor/define a interface do editor de blocos. - Um template Blade em
resources/views/blocks/renderizam a saída do frontend.
Um comando wp acorn make:block latest-posts cria LatestPosts.php, latest-posts.block.jsx e latest-posts.blade.php. O arquivo JSX define os atributos do bloco e os controles do editor, enquanto os blocos dinâmicos usam InspectorControls para adicionar configurações na barra lateral do bloco. Você importa controles de @wordpress/components e os compõe em uma interface de configurações.
import { InspectorControls } from '@wordpress/block-editor';
import { RangeControl, ToggleControl, RadioControl } from '@wordpress/components';
export const attributes = {
posts: { type: 'number', default: 5 },
displayFeaturedImage: { type: 'boolean', default: false },
postLayout: { type: 'string', default: 'list' },
};
export const edit = ({ attributes, setAttributes }) => {
return (
<>
<InspectorControls>
<RangeControl
label="Number of posts"
value={attributes.posts}
onChange={(value) => setAttributes({ posts: value })}
min={1}
max={10}
/>
<ToggleControl
label="Display featured image"
checked={attributes.displayFeaturedImage}
onChange={(value) => setAttributes({ displayFeaturedImage: value })}
/>
<RadioControl
label="Layout"
selected={attributes.postLayout}
options={[
{ label: 'List', value: 'list' },
{ label: 'Grid', value: 'grid' },
]}
onChange={(value) => setAttributes({ postLayout: value })}
/>
</InspectorControls>
</>
);
};
O filtro render_block em BlocksServiceProvider.php intercepta a renderização do bloco e passa os atributos para o template Blade. Ele também recebe o conteúdo e os dados do bloco. Você verifica o nome do bloco, consulta os dados necessários e retorna a visualização renderizada do Blade:
add_filter('render_block', function ($block_content, $block) {
if ($block['blockName'] === 'radicle/latest-posts') {
$attributes = $block['attrs'] ?? [];
$posts = get_posts([
'numberposts' => $attributes['posts'] ?? 5,
'post_status' => 'publish',
]);
return view('blocks.latest-posts', [
'posts' => $posts,
'displayFeaturedImage' => $attributes['displayFeaturedImage'] ?? false,
'postLayout' => $attributes['postLayout'] ?? 'list',
]);
}
return $block_content;
}, 10, 2);
O template Blade usa arrays PHP para gerenciar layouts condicionais. Aqui, você define as configurações de layout como arrays aninhadas que mapeiam os nomes de layout para classes CSS e elementos HTML.
@php
$layoutConfig = [
'grid' => [
'container' => 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6',
'element' => 'div',
],
'list' => [
'container' => 'space-y-6',
'element' => 'div',
],
];
$config = $layoutConfig[$postLayout];
@endphp
<div class="{{ $config['container'] }}">
@foreach ($posts as $post)
<article>
@if ($displayFeaturedImage && has_post_thumbnail($post))
{{ get_the_post_thumbnail($post, 'medium') }}
@endif
<h3>{{ $post->post_title }}</h3>
</article>
@endforeach
</div>
Esse padrão cria blocos flexíveis em que os controles do editor ajustam a saída do frontend sem duplicar a lógica do modelo: O JavaScript lida com a interface do usuário, o PHP lida com consultas de dados e o Blade lida com a estrutura de marcação.
Como o cache da Kinsta aumenta o desempenho da visualização compilada do Blade
A compilação do Blade converte essencialmente os templates do .blade.php em código PHP simples. Depois que o Blade conclui uma análise completa do template e da sintaxe do Blade, ele armazena um arquivo compilado em storage/framework/views/. Essa compilação ocorre uma vez por alteração de template e não em cada carregamento de página, mas as solicitações subsequentes ignoram a compilação e executam o PHP em cache.
O processo transforma as diretivas do Blade em funções PHP. Por exemplo, a diretiva @foreach torna-se um loop foreach; a sintaxe {{ $variable }} torna-se uma declaração echo com escape.
O cache em nível de servidor da Kinsta (Edge Caching e cache de objeto Redis) trabalha junto com o cache de compilação do Blade para criar várias camadas de desempenho. As exibições compiladas do Blade ficam entre essas camadas, que fornecem tempos de execução de templates que se beneficiam do cache upstream e da otimização downstream.
Durante a implantação, o Blade limpa o cache quando você envia alterações de template para ambientes de teste ou produção. Embora o Blade detecte modificações de template durante o desenvolvimento, seus processos de implantação devem incluir a limpeza do cache de visualização por meio da execução de php artisan view:clear ou wp acorn view:clear no script de implantação.
O desenvolvimento moderno de temas WordPress inclui Radicle e Kinsta
A combinação da estrutura inspirada no Laravel do Radicle com a infraestrutura de hospedagem gerenciada da Kinsta oferece uma base sólida para escalar projetos WordPress. Agências que gerenciam vários sites de clientes podem aproveitar padrões consistentes de componentes entre projetos. Para desenvolvedores, isso permite trabalhar com convenções familiares do Laravel, mantendo compatibilidade com o WordPress.
Seu próximo passo depende da configuração atual. Se você estiver começando do zero, comece instalando o Radicle e criando seu primeiro componente Blade. Se estiver migrando um tema existente, identifique padrões de marcação repetitivos e converta-os em componentes, uma seção por vez. Concentre-se em áreas de alto impacto, como navegação, cabeçalhos e rodapés, onde os benefícios dos componentes aparecem imediatamente.
Se você precisa de hospedagem gerenciada para WordPress que suporte fluxos de desenvolvimento modernos, a Kinsta oferece recursos que funcionam com ferramentas como Radicle e Acorn.