El desarrollo tradicional de temas de WordPress se basa en repetir el marcado del encabezado y el pie de página en todos los archivos de plantilla. Cada vez que actualizas un menú de navegación o un elemento del pie de página, debes localizar todos los archivos de plantilla que incluyen el marcado y realizar los cambios necesarios en varias ubicaciones. Esto genera gastos de mantenimiento y aumenta el riesgo de inconsistencias en tu sitio.
Radicle lleva el motor de plantillas Blade de Laravel a WordPress a través de la arquitectura basada en componentes de Acorn. En lugar de dispersar el marcado por los archivos de plantilla, defines componentes reutilizables una sola vez y los referencias a lo largo de tu tema. Cuando necesitas actualizar un elemento de la interfaz de usuario, modificas un único archivo de componente en lugar de buscar entre docenas de plantillas.
Por qué el desarrollo de plantillas de WordPress necesita una arquitectura basada en componentes
WordPress almacena las plantillas en una estructura de directorios de temas en la que header.php y footer.php aparecen en cada plantilla de página a través de llamadas a get_header() y get_footer(). Esto funciona para sitios básicos, pero causa problemas cuando se escala en proyectos complejos.
Por ejemplo, un sitio con tipos de entrada personalizados, páginas de destino y plantillas de marketing incluye el mismo marcado de navegación, estructura de pie de página y elementos de barra lateral en cada archivo de plantilla. Esto te obliga a buscar en varios archivos de plantilla para añadir un nuevo elemento de menú o actualizar un formulario de contacto en el pie de página.
Radicle organiza las plantillas Blade en resources/views/ con directorios separados para diseños, componentes y Bloques:
components. Este directorio incluye elementos de interfaz de usuario independientes, como encabezados y botones.layouts. Contiene plantillas estructurales que definen el andamiaje de la página.blocks.Aquí se almacenan las plantillas de bloque que se integran con el Editor de Sitios de WordPress.
Esta organización crea una única fuente de verdad (single source of truth) para cada elemento de IU. Un componente x-heading define el marcado y el estilo de los encabezados en una única ubicación. Así, cuando utilizas este componente en varias plantillas, Blade hace referencia a la definición única. Por extensión, al actualizar el componente se actualizan todas las instancias de tu sitio.
Cómo crear diseños maestros que eliminen la duplicación de código
En lugar de duplicar el marcado de la navegación y el pie de página, puedes utilizar la herencia de plantillas para crear un diseño maestro que defina la estructura base del sitio.
Un diseño comienza con un archivo de componentes Blade en resources/views/components/. El archivo layout.blade.php define la estructura HTML que envuelve el contenido de la página. Esto incluye el doctype, la sección head con metaetiquetas y referencias a activos, la estructura de navegación y los elementos de pie de página. El elemento clave en un diseño es la variable $slot, que Blade utiliza como punto de inyección de contenido.
<html>
<head>
<title>{{ $title ?? 'My Site' }}</title>
</head>
<body>
<nav>
</nav>
<main>
{{ $slot }}
</main>
<footer>
</footer>
</body>
</html>
Las plantillas hijas amplían este diseño utilizando la sintaxis de componentes de Blade. Una plantilla de página envuelve su contenido en las etiquetas de componente x-layout. Blade procesa esto renderizando el componente de diseño e inyectando el contenido hijo donde aparece la variable $slot:
<x-layout>
<h1>Page Title</h1>
<p>Page content goes here.</p>
</x-layout>
Los slots con nombre proporcionan puntos de inyección adicionales para el contenido dinámico (como los títulos de página). En lugar de aceptar un slot por defecto, defines slots específicos con nombres. El componente x-slot con un atributo name pasa contenido a estas ubicaciones designadas:
<x-layout>
<x-slot name="title">
Custom Page Title
</x-slot>
<h1>Page Heading</h1>
<p>Page content.</p>
</x-layout>
El componente de diseño accede a los slots con nombre a través de variables que coinciden con los nombres de los slots. Esto te permite inyectar contenido en varias ubicaciones de diseño desde una única plantilla hija.
Crear componentes de interfaz de usuario reutilizables para patrones de diseño coherentes
Los componentes Blade centralizan el estilo y el marcado de los elementos comunes de la interfaz.
En lugar de escribir el marcado de un botón con clases Tailwind en cada plantilla, crea un componente de botón que encapsule el marcado. El componente acepta «accesorios» para su personalización, al tiempo que mantiene un estilo base coherente.
Utilizar el componente x-heading con otros componentes tipográficos es un buen ejemplo de ello. Acepta una «prop» level que determina el elemento HTML (h1, h2, h3) y una «prop» size que controla la escala visual. El componente mapea internamente estas props a clases Tailwind, lo que mantiene separados los detalles de implementación.
<x-heading level="h1" size="3xl">
Main Page Title
</x-heading>
<x-heading level="h2" size="2xl">
Section Heading
</x-heading>
El archivo del componente en resources/views/components/heading.blade.php define la lógica de marcado y estilo utilizando la directiva @props de Blade para definir las propiedades aceptadas y sus valores predeterminados. Cada componente construye el elemento HTML apropiado con clases basadas en los valores de las propiedades.
Un componente x-link sigue el mismo patrón con soporte para variantes de estilo, donde una propiedad (prop) variant permite alternar entre presentaciones predeterminadas, de tipo botón o sin estilos.
Los componentes de interfaz de usuario como x-button te permiten conseguir lo mismo con elementos interactivos. El componente button admite props de tamaño y variantes para diferentes estilos de botón. Cuando lo combinas con un framework como Alpine.js a través del componente x-modal, puedes gestionar interacciones sin dispersar JavaScript por las plantillas:
<x-button variant="primary" @click="showModal = true">
Open Modal
</x-button>
<x-modal x-show="showModal">
<p>Modal content</p>
</x-modal>
Los props funcionan bien para cadenas, booleanos y otros datos sencillos. Los slots sirven mejor para contenido complejo que incluya marcado. Por ejemplo, el componente modal utiliza un slot predeterminado para aceptar todo el contenido modal en lugar de pasar HTML a través de un prop.
Conectar datos de WordPress a plantillas Blade con compositores de vistas
Los View Composers te permiten agregar datos de múltiples fuentes antes de renderizar una plantilla. Aquí, creas una clase composer que se encarga de la recuperación y transformación de los datos en lugar de consultar las entradas directamente en las plantillas. De este modo, la plantilla recibe datos estructurados para mostrarlos.
El modelo Post de Radicle simplifica el trabajo con los datos de las entradas de WordPress utilizando algunos métodos diferentes:
title()devuelve el título de la entrada.- El método
content()recupera el contenido filtrado de la entrada. excerpt()acepta un recuento de palabras y genera un extracto.permalink()devuelve la URL de la entrada.
Para las imágenes destacadas, hasThumbnail() comprueba si existe una imagen, y thumbnail() recupera el HTML de la imagen con un tamaño especificado:
$post = Post::find(123);
echo $post->title();
echo $post->excerpt(30);
if ($post->hasThumbnail()) {
echo $post->thumbnail('large');
}
Los View Composers se pueden ver en tiempo real en app/View/Composers/ y extienden Roots\Acorn\View\Composer. La clase define a qué vistas se aplica a través de la propiedad estática protegida $views, que acepta un array de nombres de plantillas. Para un compositor de página principal, se especifica “front-page” para apuntar a la plantilla 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(),
];
}
}
El método with() devuelve un array cuyas claves se convierten en nombres de variables de la plantilla. Los valores pueden ser colecciones Eloquent, modelos individuales o cualquier estructura de datos. En cualquier caso, este método se ejecuta antes de que cualquier plantilla renderice y prepare los datos.
La plantilla front-page.blade.php accede directamente a estas variables. La directiva @foreach de Blade realiza un bucle a través de las entradas, y cada iteración proporciona acceso a los métodos del modelo Post:
<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>
En este patrón, el compositor se encarga de las consultas y la transformación de datos, mientras que la plantilla se centra en la lógica de marcado y visualización. Cuando necesites modificar la estructura de datos o añadir nuevas consultas, actualiza el compositor sin tocar los archivos de la plantilla.
Bloques de construcción para el Editor de Sitios de WordPress con renderizado Blade
Radicle utiliza la renderización del lado del servidor para los Bloques del Editor de Sitios mediante plantillas Blade. El componente JavaScript del editor se encarga de la interfaz del Bloque en el admin de WordPress, y la plantilla Blade se encarga de la salida del frontend.
Esto te permite crear interfaces de bloque con React (por ejemplo) mientras renderizas el HTML de producción con Blade.
El comando wp acorn make:block genera tres archivos para cada Bloque:
- Una clase PHP en
app/Blocks/gestiona la lógica del lado del servidor. - El componente JSX en
resources/js/editor/define la interfaz del editor de bloques. - Las plantillas Blade en
resources/views/blocks/renderizan la salida del frontend.
El comando wp acorn make:block latest-posts crea LatestPosts.php, latest-posts.block.jsx, y latest-posts.blade.php. El archivo JSX define los atributos del bloque y los controles del editor, mientras que los bloques dinámicos utilizan InspectorControls para añadir ajustes en la barra lateral del bloque. Estos controles se importan desde@wordpress/components y se combinan para crear una interfaz de configuración personalizada.
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>
</>
);
};
El filtro render_block en BlocksServiceProvider.php intercepta la renderización del Bloque y pasa los atributos a la plantilla Blade. También recibe el contenido del Bloque y los datos del Bloque. Comprueba el nombre del Bloque, consulta los datos necesarios y devuelve la vista Blade renderizada:
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);
La plantilla Blade utiliza arrays PHP para gestionar diseños condicionales. Aquí, defines las configuraciones de diseño como arrays anidados que asignan nombres de diseño a clases CSS y 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>
Este patrón crea bloques flexibles en los que los controles del editor ajustan la salida del frontend sin duplicar la lógica de la plantilla: JavaScript se encarga de la interfaz de usuario, PHP de las consultas de datos y Blade de la estructura de marcado.
Cómo el almacenamiento en caché de Kinsta aumenta el rendimiento de la vista compilada de Blade
La compilación de Blade básicamente convierte las plantillas de .blade.php en código PHP sin formato. Después de que Blade complete un análisis completo de la plantilla y de la sintaxis de Blade, almacena un archivo compilado en storage/framework/views/. Esta compilación se produce una vez por cada cambio de plantilla en lugar de en cada carga de página, pero las peticiones posteriores se saltan la compilación y ejecutan el PHP almacenado en caché.
El proceso transforma las directivas Blade en funciones PHP. Por ejemplo, la directiva @foreach se convierte en un bucle foreach; la sintaxis {{ $variable }} se convierte en una sentencia echo con escapes.
El almacenamiento en caché a nivel de servidor de Kinsta (tanto edge caching como la caché de objetos Redis) funciona junto con la caché de compilación de Blade para crear múltiples niveles de rendimiento. Las vistas compiladas de Blade se sitúan entre estas capas, que proporcionan tiempos de ejecución de plantillas que se benefician tanto del almacenamiento en caché ascendente como de la optimización descendente.
Durante el despliegue, Blade borra la caché cuando introduces cambios en las plantillas en los entornos staging o producción. Aunque Blade detecta las modificaciones de las plantillas durante el desarrollo, tus procesos de despliegue deben incluir la limpieza de la caché de vistas mediante la ejecución de php artisan view:clear o wp acorn view:clear dentro de tu script de despliegue.
El desarrollo moderno de temas de WordPress incluye Radicle y Kinsta
La combinación de la estructura inspirada en Laravel de Radicle y la infraestructura de alojamiento administrado de Kinsta te proporciona una base para escalar proyectos de WordPress. Las agencias que gestionan sitios de varios clientes pueden aprovechar patrones de componentes coherentes en todos los proyectos. Para los desarrolladores, puedes trabajar con las convenciones familiares de Laravel manteniendo la compatibilidad con WordPress.
Tu siguiente paso depende de tu configuración actual. Si estás empezando de cero, empieza por instalar Radicle y crear tu primer componente Blade. Si estás migrando un tema existente, identifica los patrones de marcado repetitivos y conviértelos en componentes, sección por sección. Céntrate en las áreas de alto valor, como la navegación, las cabeceras y los pies de página, donde los beneficios de los componentes son inmediatos.
Si necesitas un alojamiento administrado para WordPress que admita flujos de trabajo de desarrollo modernos, Kinsta ofrece funcionalidades que son compatibles con herramientas como Radicle y Acorn.