Lo sviluppo tradizionale di un tema WordPress si basa sulla ripetizione del markup dell’header e del footer nei vari file di template. Ogni volta che aggiorni un menu di navigazione o un elemento del footer, devi individuare tutti i file di template che includono il markup e apportare le modifiche necessarie in più posizioni. Questo crea costi di manutenzione eccessivi e aumenta il rischio di incongruenze nel sito.

Radicle porta il motore di template Blade di Laravel su WordPress grazie all’architettura basata su componenti di Acorn. Invece di sparpagliare il markup nei file di template, definisci i componenti riutilizzabili una sola volta e fai riferimento ad essi in tutto il tuo tema. Quando devi aggiornare un elemento dell’interfaccia utente, basta modificare un singolo file di componente invece di cercare tra decine di template.

Perché lo sviluppo di template WordPress ha bisogno di un’architettura basata sui componenti

WordPress memorizza i template in una struttura di directory di temi in cui header.php e footer.php appaiono in ogni template di pagina attraverso le chiamate get_header() e get_footer(). Questo sistema funziona per i siti di base, ma causa problemi quando si tratta di scalare su progetti complessi.

Ad esempio, un sito con tipi di post personalizzati, landing page e template di marketing include lo stesso markup di navigazione, la stessa struttura del footer e gli stessi elementi della barra laterale in ogni file di template. Questa disposizione obbliga a cercare tra più file di template per aggiungere una nuova voce di menu o aggiornare un modulo di contatto nel footer.

Radicle organizza i template Blade in resources/views/ con directory separate per i layout, i componenti e i blocchi:

  • components. Questa directory include elementi UI autonomi come intestazioni e pulsanti.
  • layouts. Questa contiene i template strutturali che definiscono l’impalcatura della pagina.
  • blocks. Qui vengono archiviati i template di blocco che si integrano con l’editor del sito WordPress.

Questa organizzazione crea un’unica fonte per ogni elemento dell’interfaccia utente. Un componente x-heading definisce il markup e lo stile dell’header in un’unica posizione. Quindi, utilizzando questo componente in tutti i template, Blade fa riferimento alla singola definizione. Per estensione, l’aggiornamento del componente aggiorna ogni istanza del sito.

Come costruire layout primari che eliminano il codice duplicato

Invece di duplicare il markup della navigazione e del footer, puoi utilizzare l’ereditarietà dei template per creare un layout principale che definisca la struttura del sito.

Un layout inizia con un file componente Blade in resources/views/components/. Il file layout.blade.php definisce la struttura HTML che avvolge il contenuto della pagina. Include la sezione doctype, la sezione dell’head con i meta tag e i riferimenti alle risorse, la struttura di navigazione e gli elementi del footer. L’elemento chiave di un layout è la variabile $slot, che Blade utilizza come punto di iniezione del contenuto.

<html>
<head>
    <title>{{ $title ?? 'My Site' }}</title>
</head>

<body>
    <nav>
        
    </nav>

    <main>
        {{ $slot }}
    </main>

    <footer>
        
    </footer>

</body>
</html>

I template child estendono questo layout utilizzando la sintassi dei componenti di Blade. Un template di pagina avvolge il suo contenuto nei tag del componente x-layout. Blade elabora il tutto eseguendo il rendering del componente di layout e iniettando il contenuto child dove appare la variabile $slot:

<x-layout>
    <h1>Page Title</h1>
    <p>Page content goes here.</p>
</x-layout>

Gli slot denominati forniscono ulteriori punti di iniezione per i contenuti dinamici (come i titoli delle pagine). Invece di accettare uno slot predefinito, puoi definire degli slot specifici con dei nomi. Il componente x-slot con l’attributo name passa il contenuto in queste posizioni designate:

<x-layout>
    <x-slot name="title">
        Custom Page Title
    </x-slot>

    <h1>Page Heading</h1>
    <p>Page content.</p>
</x-layout>

Il componente layout accede agli slot denominati attraverso le variabili che corrispondono ai nomi degli slot. In questo modo puoi iniettare il contenuto in più posizioni del layout da un unico template child.

Creare componenti UI riutilizzabili per template di design coerenti

I componenti Blade centralizzano lo stile e il markup degli elementi comuni dell’interfaccia.

Invece di scrivere il markup dei pulsanti con le classi di Tailwind in ogni template, puoi creare un componente pulsante che incapsula il markup. Il componente accetta “prop” per la personalizzazione, pur mantenendo uno stile di base coerente.

L’utilizzo del componente x-heading con altri componenti tipografici ne è un buon esempio. Accetta un oggetto level che determina l’elemento HTML (h1, h2, h3) e un oggetto size che controlla la scala visiva. Il componente mappa internamente questi prop in classi di Tailwind, in modo da mantenere separati i dettagli dell’implementazione.

<x-heading level="h1" size="3xl">
    Main Page Title
</x-heading>

<x-heading level="h2" size="2xl">
    Section Heading
</x-heading>

Il file del componente in resources/views/components/heading.blade.php definisce la logica di markup e styling utilizzando la direttiva @props di Blade per definire le proprietà accettate e i loro valori predefiniti. Ogni componente costruisce l’elemento HTML appropriato con le classi basate sui valori delle proprietà.

Un componente x-link segue lo stesso schema con il supporto di varianti per i diversi stili di link, mentre una variante di prop permette di passare dalle presentazioni predefinite, ai pulsanti e alle presentazioni senza stile.

I componenti UI come x-button permettono di ottenere lo stesso risultato con gli elementi interattivi. Il componente button supporta le dimensioni e le varianti per i diversi stili dei pulsanti. Se lo combini con un framework come Alpine.js attraverso il componente x-modal, puoi gestire le interazioni senza disperdere JavaScript nei template:

<x-button variant="primary" @click="showModal = true">
    Open Modal
</x-button>

<x-modal x-show="showModal">
    <p>Modal content</p>
</x-modal>

I prop funzionano bene per stringhe, booleani e altri dati semplici. Gli slot sono più adatti per contenuti complessi che includono markup. Ad esempio, il componente modal utilizza uno slot predefinito per accettare il contenuto modale completo piuttosto che passare l’HTML attraverso un prop.

Collegare i dati di WordPress ai template Blade con i compositori di viste

I compositori di viste permettono di aggregare i dati da più fonti prima di renderizzare un template. In questo caso, crei una classe composer che gestisce il recupero e la trasformazione dei dati piuttosto che interrogare i post direttamente nei template. Invece, il template riceve i dati strutturati da visualizzare.

Il template Post di Radicle semplifica il lavoro con i dati dei post di WordPress utilizzando alcuni metodi diversi:

  • title() restituisce il titolo del post.
  • Il metodo content() recupera il contenuto del post filtrato.
  • excerpt() accetta un conteggio di parole e genera un estratto.
  • permalink() restituisce l’URL del post.

Per le immagini in evidenza, hasThumbnail() controlla se esiste un’immagine e thumbnail() recupera l’HTML dell’immagine con una dimensione specificata:

$post = Post::find(123);
echo $post->title();
echo $post->excerpt(30);
if ($post->hasThumbnail()) {
    echo $post->thumbnail('large');
}

Le classi di compositori di viste si trovano in app/View/Composers/ ed estendono RootsAcornViewComposer. La classe definisce le viste a cui si applica attraverso la proprietà statica protetta $views, che accetta un array di nomi di template. Per un compositore di prima pagina, è necessario specificare 'front-page' per puntare al 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(),
        ];
    }
}

Il metodo with() restituisce un array in cui le chiavi diventano nomi di variabili nel template. I valori possono essere collezioni Eloquent, singoli template o qualsiasi struttura di dati. In ogni caso, questo metodo viene eseguito prima che qualsiasi template esegua il rendering e prepari i dati.

Il template front-page.blade.php accede direttamente a queste variabili. La direttiva @foreach di Blade esegue un ciclo di post e ogni iterazione fornisce l’accesso ai metodi del template 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>

In questo schema, il compositore gestisce l’interrogazione e la trasformazione dei dati, mentre il template si concentra sul markup e sulla logica di visualizzazione. Per modificare la struttura dei dati o aggiungere nuove query, aggiorna il compositore senza toccare i file del template.

Blocchi di costruzione per l’editor di siti WordPress con rendering Blade

Radicle utilizza il rendering lato server per i blocchi dell’editor del sito attraverso i template Blade. Il componente editor JavaScript gestisce l’interfaccia del blocco nell’amministrazione di WordPress, mentre il template Blade gestisce l’output del frontend.

In questo modo puoi creare interfacce per i blocchi con React (ad esempio) e allo stesso tempo eseguire il rendering dell’HTML di produzione con Blade.

Il comando wp acorn make:block genera tre file per ogni blocco:

  • Una classe PHP in app/Blocks/ gestisce la logica lato server.
  • Il componente JSX in resources/js/editor/ definisce l’interfaccia dell’editor del blocco.
  • Il template Blade in resources/views/blocks/ rende l’output del frontend.

Un comando wp acorn make:block latest-posts crea LatestPosts.php, latest-posts.block.jsx e latest-posts.blade.php. Il file JSX definisce gli attributi e i controlli dell’editor del blocco, mentre i blocchi dinamici utilizzano InspectorControls per aggiungere le impostazioni nella barra laterale del blocco. Si importano i controlli da @wordpress/components e li si compone in un’interfaccia di impostazioni.

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>
        </>
    );
};

Il filtro render_block in BlocksServiceProvider.php intercetta il rendering del blocco e passa gli attributi al template Blade. Riceve anche il contenuto del blocco e i dati del blocco. Controlla il nome del blocco, interroga i dati necessari e restituisce la vista Blade renderizzata:

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);

Il template Blade utilizza gli array PHP per gestire i layout condizionali. Qui definisci le configurazioni di layout come array annidati che mappano i nomi dei layout alle classi CSS e agli elementi 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>

Questo schema crea blocchi flessibili in cui i controlli dell’editor regolano l’output del frontend senza duplicare la logica del template: JavaScript gestisce l’interfaccia utente, PHP le query di dati e Blade la struttura del markup.

Come la cache di Kinsta aumenta le prestazioni delle viste compilate di Blade

La compilazione di Blade converte essenzialmente i template di .blade.php in semplice codice PHP. Dopo aver completato l’analisi completa del template e della sintassi di Blade, Blade salva un file compilato in storage/framework/views/. Questa compilazione avviene una volta per ogni modifica del template anziché a ogni caricamento della pagina, ma le richieste successive saltano la compilazione ed eseguono il PHP in cache.

Il processo trasforma le direttive di Blade in funzioni PHP. Ad esempio, la direttiva @foreach diventa un ciclo foreach; la sintassi {{ $variable }} diventa un’istruzione echo con escape.

La cache a livello di server di Kinsta (sia la cache edge che la cache degli oggetti di Redis) lavora insieme alla cache di compilazione di Blade per creare più livelli di prestazioni. Le viste compilate di Blade si collocano tra questi livelli e forniscono tempi di esecuzione dei template che beneficiano sia della cache a monte che dell’ottimizzazione a valle.

Durante la distribuzione, Blade cancella la cache quando si apportano modifiche ai template negli ambienti di staging o di produzione. Sebbene Blade rilevi le modifiche ai template durante lo sviluppo, i processi di distribuzione dovrebbero includere la cancellazione della cache delle viste attraverso l’esecuzione di php artisan view:clear o wp acorn view:clear all’interno dello script di distribuzione.

Lo sviluppo moderno di temi WordPress include Radicle e Kinsta

La combinazione tra la struttura ispirata a Laravel di Radicle e l’infrastruttura di hosting gestito di Kinsta offre una base per scalare i progetti WordPress. Le agenzie che gestiscono più siti di clienti possono sfruttare template di componenti coerenti tra i vari progetti. Gli sviluppatori possono lavorare con le convenzioni di Laravel, pur mantenendo la compatibilità con WordPress.

Il passo successivo dipende dalla tua configurazione attuale. Se stai iniziando da zero, inizia installando Radicle e creando il tuo primo componente Blade. Se stai migrando un tema esistente, identifica i template di markup ripetitivi e convertili in componenti una sezione alla volta. Concentrati su aree di grande valore come la navigazione, gli header e i footer, dove i vantaggi dei componenti sono immediati.

Se hai bisogno di un hosting WordPress gestito che supporti i moderni flussi di sviluppo, Kinsta offre funzionalità compatibili con strumenti come Radicle e Acorn.

Joel Olawanle Kinsta

Joel è uno Frontend developer che lavora in Kinsta come redattore tecnico. È un insegnante appassionato che ama l'open source e ha scritto oltre 200 articoli tecnici principalmente su JavaScript e i suoi framework.