Bei der herkömmlichen WordPress-Theme-Entwicklung wird das Header- und Footer-Markup in allen Vorlagendateien wiederholt. Jedes Mal, wenn du ein Navigationsmenü oder ein Fußzeilenelement aktualisierst, musst du jede Vorlagendatei finden, die das Markup enthält, und die notwendigen Änderungen an mehreren Stellen vornehmen. Das verursacht einen hohen Wartungsaufwand und erhöht das Risiko von Inkonsistenzen auf deiner Website.
Radicle bringt die Blade-Templating-Engine von Laravel über die komponentenbasierte Architektur von Acorn zu WordPress. Anstatt das Markup über mehrere Vorlagendateien zu verstreuen, definierst du wiederverwendbare Komponenten einmal und referenzierst sie in deinem Theme. Wenn du ein UI-Element aktualisieren musst, änderst du eine einzige Komponentendatei, anstatt Dutzende von Vorlagen zu durchsuchen.
Warum die Entwicklung von WordPress-Templates eine komponentenbasierte Architektur braucht
WordPress speichert Vorlagen in einer Theme-Verzeichnisstruktur, in der header.php und footer.php in jeder Seitenvorlage durch get_header() und get_footer() Aufrufe erscheinen. Das funktioniert für einfache Websites, führt aber zu Problemen bei der Skalierung über komplexe Projekte hinweg.
Eine Website mit benutzerdefinierten Beitragstypen, Landing Pages und Marketingvorlagen enthält zum Beispiel in jeder Vorlagendatei dasselbe Navigationsmarkup, dieselbe Fußzeilenstruktur und dieselben Seitenleistenelemente. Dadurch musst du mehrere Vorlagendateien durchsuchen, um einen neuen Menüpunkt hinzuzufügen oder ein Kontaktformular in der Fußzeile zu aktualisieren.
Radicle organisiert die Blade-Vorlagen in resources/views/ mit separaten Verzeichnissen für Layouts, Komponenten und Blöcke:
components. Dieses Verzeichnis enthält in sich geschlossene UI-Elemente wie Überschriften und Schaltflächen.layouts. Hier werden Strukturvorlagen gespeichert, die das Seitengerüst definieren.blocks.Hier speicherst du Blockvorlagen, die in den WordPress-Site-Editor integriert werden.
Diese Organisation schafft eine einzige Quelle der Wahrheit für jedes UI-Element. Eine x-heading Komponente definiert die Überschriftenauszeichnung und das Styling an einem Ort. Wenn du diese Komponente also in verschiedenen Vorlagen verwendest, verweist Blade auf diese eine Definition. Wenn du die Komponente aktualisierst, wird jede Instanz auf deiner Website aktualisiert.
Wie du primäre Layouts erstellst, die doppelten Code vermeiden
Anstatt das Navigations- und Fußzeilenlayout zu duplizieren, kannst du mit Hilfe der Vorlagenvererbung ein übergeordnetes Layout erstellen, das die Site Shell definiert.
Ein Layout beginnt mit einer Blade-Komponentendatei in resources/views/components/. Die Datei layout.blade.php definiert die HTML-Struktur, die den Inhalt der Seite umschließt. Dazu gehören der doctype, der Kopfbereich mit Metatags und Asset-Referenzen, die Navigationsstruktur und die Fußzeilenelemente. Das Schlüsselelement in einem Layout ist die Variable $slot, die Blade als Einfügepunkt für den Inhalt verwendet.
<html>
<head>
<title>{{ $title ?? 'My Site' }}</title>
</head>
<body>
<nav>
<!-- Navigation markup -->
</nav>
<main>
{{ $slot }}
</main>
<footer>
<!-- Footer markup -->
</footer>
</body>
</html>
Untergeordnete Vorlagen erweitern dieses Layout mithilfe der Komponentensyntax von Blade. Eine Seitenvorlage umhüllt ihren Inhalt mit den x-layout Komponenten-Tags. Blade verarbeitet dies, indem es die Layoutkomponente rendert und den untergeordneten Inhalt dort einfügt, wo die Variable $slot erscheint:
<x-layout>
<h1>Page Title</h1>
<p>Page content goes here.</p>
</x-layout>
Benannte Slots bieten zusätzliche Einfügepunkte für dynamische Inhalte (wie z. B. Seitentitel). Anstatt einen Standard-Slot zu akzeptieren, definierst du bestimmte Slots mit Namen. Die Komponente x-slot mit dem Attribut name leitet Inhalte an diese benannten Stellen weiter:
<x-layout>
<x-slot name="title">
Custom Page Title
</x-slot>
<h1>Page Heading</h1>
<p>Page content.</p>
</x-layout>
Die Layoutkomponente greift auf die benannten Slots über Variablen zu, die den Slotnamen entsprechen. Auf diese Weise kannst du Inhalte von einer einzigen Child-Vorlage aus in mehrere Layoutbereiche einfügen.
Wiederverwendbare UI-Komponenten für konsistente Designmuster erstellen
Blade-Komponenten zentralisieren das Styling und Markup für allgemeine Oberflächenelemente.
Anstatt das Markup für Schaltflächen mit Tailwind-Klassen in jeder Vorlage zu schreiben, erstellst du eine Schaltflächenkomponente, die das Markup kapselt. Die Komponente akzeptiert „Requisiten“ zur Anpassung und behält gleichzeitig ein konsistentes Basis-Styling bei.
Die Verwendung der Komponente x-heading mit anderen Typografiekomponenten ist ein gutes Beispiel dafür. Sie akzeptiert eine level Requisite, die das HTML-Element bestimmt (h1, h2, h3) und eine size Requisite, die den visuellen Maßstab steuert. Die Komponente bildet diese Requisiten intern auf Tailwind-Klassen ab, wodurch die Implementierungsdetails getrennt bleiben.
<x-heading level="h1" size="3xl">
Main Page Title
</x-heading>
<x-heading level="h2" size="2xl">
Section Heading
</x-heading>
Die Komponentendatei in resources/views/components/heading.blade.php definiert die Markup- und Stylinglogik, indem sie die Blade-Direktive @props verwendet, um die akzeptierten Eigenschaften und ihre Standardwerte zu definieren. Jede Komponente konstruiert das entsprechende HTML-Element mit Klassen, die auf den Eigenschaftswerten basieren.
Die Komponente x-link folgt demselben Muster, wobei verschiedene Linkstile unterstützt werden, und ein Variant-Prop schaltet zwischen Standard-, Button- und ungestylter Darstellung um.
Mit UI-Komponenten wie x-button kannst du dasselbe mit interaktiven Elementen erreichen. Die Komponente button unterstützt Größen- und Variantenrequisiten für verschiedene Schaltflächenstile. Wenn du sie über die Komponente x-modal mit einem Framework wie Alpine.js kombinierst, kannst du Interaktionen steuern, ohne JavaScript über die Vorlagen zu verstreuen:
<x-button variant="primary" @click="showModal = true">
Open Modal
</x-button>
<x-modal x-show="showModal">
<p>Modal content</p>
</x-modal>
Props eignen sich gut für Strings, Booleans und andere einfache Daten. Slots eignen sich besser für komplexe Inhalte, die Markup enthalten. Die Komponente modal verwendet zum Beispiel einen Standardslot, um den vollständigen modalen Inhalt zu akzeptieren, anstatt HTML über eine Requisite zu übergeben.
Verbinden von WordPress-Daten mit Blade-Vorlagen mit View Composern
Mit View Composers kannst du Daten aus verschiedenen Quellen zusammenfassen, bevor du eine Vorlage renderst. Hier erstellst du eine composer Klasse, die die Datenabfrage und -umwandlung übernimmt, anstatt die Beiträge direkt in den Vorlagen abzufragen. Stattdessen erhält die Vorlage strukturierte Daten zur Anzeige.
Das Post Modell von Radicle vereinfacht die Arbeit mit WordPress-Beitragsdaten durch verschiedene Methoden:
title()gibt den Beitragstitel zurück.- Die Methode
content()ruft den gefilterten Inhalt des Beitrags ab. excerpt()akzeptiert eine Wortzahl und generiert einen Auszug.permalink()gibt die URL des Beitrags zurück.
Für Bilder prüft hasThumbnail(), ob ein Bild vorhanden ist, und thumbnail() ruft das HTML-Bild mit einer bestimmten Größe ab:
$post = Post::find(123);
echo $post->title();
echo $post->excerpt(30);
if ($post->hasThumbnail()) {
echo $post->thumbnail('large');
}
Die View Composer-Klassen befinden sich in app/View/Composers/ und erweitern RootsAcornViewComposer. Die Klasse legt über die geschützte statische Eigenschaft $views, die ein Array von Vorlagennamen akzeptiert, fest, für welche Ansichten sie gilt. Für einen Frontpage Composer gibst du 'front-page' an, um die Vorlage front-page.blade.php zu verwenden:
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(),
];
}
}
Die Methode with() gibt ein Array zurück, dessen Schlüssel zu Variablennamen in der Vorlage werden. Die Werte können Eloquent-Sammlungen, einzelne Modelle oder beliebige Datenstrukturen sein. In jedem Fall wird diese Methode vor dem Rendern der Vorlage ausgeführt und bereitet die Daten auf.
Die Vorlage front-page.blade.php greift direkt auf diese Variablen zu. Die Blade-Direktive @foreach durchläuft eine Schleife, und jede Iteration ermöglicht den Zugriff auf die Methoden des Post-Modells:
<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>
Bei diesem Muster kümmert sich der Composer um die Abfragen und die Datenumwandlung, während sich die Vorlage auf das Markup und die Anzeigelogik konzentriert. Wenn du die Datenstruktur ändern oder neue Abfragen hinzufügen musst, aktualisierst du den Composer, ohne die Vorlagendateien anzufassen.
Bausteine für den WordPress-Site-Editor mit Blade-Rendering
Radicle nutzt das serverseitige Rendering für Site-Editor-Blöcke über Blade-Vorlagen. Die JavaScript-Editor-Komponente kümmert sich um die Block-Schnittstelle im WordPress-Admin und die Blade-Vorlage um die Frontend-Ausgabe.
Auf diese Weise kannst du Block-Schnittstellen z. B. mit React erstellen und gleichzeitig das Produktions-HTML mit Blade rendern.
Der Befehl wp acorn make:block erzeugt drei Dateien für jeden Block:
- Eine PHP-Klasse in
app/Blocks/verwaltet die serverseitige Logik. - Die JSX-Komponente in
resources/js/editor/definiert die Schnittstelle des Block-Editors. - Blade Templates in
resources/views/blocks/rendert die Frontend-Ausgabe.
Ein wp acorn make:block latest-posts Befehl erstellt LatestPosts.php, latest-posts.block.jsx und latest-posts.blade.php. Die JSX-Datei definiert die Attribute des Blocks und die Steuerelemente des Editors, während die dynamischen Blöcke InspectorControls verwenden, um Einstellungen in der Seitenleiste des Blocks hinzuzufügen. Du importierst Steuerelemente aus @wordpress/components und stellst sie zu einer Einstellungsoberfläche zusammen.
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>
</>
);
};
Der Filter render_block in BlocksServiceProvider.php fängt das Rendering des Blocks ab und gibt die Attribute an die Blade-Vorlage weiter. Er empfängt auch den Blockinhalt und die Blockdaten. Du prüfst den Blocknamen, fragst die erforderlichen Daten ab und gibst die gerenderte Blade-Ansicht zurück:
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);
Die Blade-Vorlage verwendet PHP-Arrays, um bedingte Layouts zu verwalten. Hier definierst du Layoutkonfigurationen als verschachtelte Arrays, die Layoutnamen auf CSS-Klassen und HTML-Elemente abbilden.
@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>
Auf diese Weise entstehen flexible Blöcke, in denen die Redakteure die Frontend-Ausgabe anpassen, ohne die Vorlagenlogik zu duplizieren: JavaScript kümmert sich um die Benutzeroberfläche, PHP um die Datenabfragen und Blade um die Markup-Struktur.
Wie das Caching von Kinsta die Leistung der kompilierten Blade-Ansicht steigert
Bei der Kompilierung von Blade werden die .blade.php Vorlagen in einfachen PHP-Code umgewandelt. Nachdem Blade die Vorlage und die Blade-Syntax vollständig geparst hat, speichert es eine kompilierte Datei auf storage/framework/views/. Diese Kompilierung erfolgt einmal pro Vorlagenänderung und nicht bei jedem Laden der Seite. Bei nachfolgenden Anfragen wird die Kompilierung übersprungen und PHP aus dem Cache ausgeführt.
Der Prozess wandelt Blade-Direktiven in PHP-Funktionen um. Die Direktive @foreach wird zum Beispiel zu einer foreach Schleife; die Syntax {{ $variable }} wird zu einer echo Anweisung mit Escaping.
Kinstas Caching auf Serverebene (sowohl Edge Caching als auch Redis Object Caching) arbeitet mit dem Compilation Cache von Blade zusammen, um mehrere Leistungsebenen zu schaffen. Die kompilierten Blade-Ansichten befinden sich zwischen diesen Ebenen und sorgen für Ausführungszeiten der Vorlagen, die sowohl vom vorgelagerten Caching als auch von der nachgelagerten Optimierung profitieren.
Während der Bereitstellung löscht Blade den Cache, wenn du Änderungen an den Vorlagen in die Staging- oder Produktionsumgebung überträgst. Obwohl Blade Änderungen an Vorlagen während der Entwicklung erkennt, sollten deine Bereitstellungs-Prozesse das Löschen des View-Caches durch die Ausführung von php artisan view:clear oder wp acorn view:clear innerhalb deines Bereitstellungs-Skripts beinhalten.
Moderne WordPress-Theme-Entwicklung mit Radicle und Kinsta
Die Kombination aus der von Laravel inspirierten Struktur von Radicle und der Managed-Hosting-Infrastruktur von Kinsta bietet dir eine Grundlage für die Skalierung von WordPress-Projekten. Agenturen, die mehrere Kunden-Websites verwalten, können projektübergreifend einheitliche Komponentenmuster nutzen. Entwickler können mit den vertrauten Laravel-Konventionen arbeiten und gleichzeitig die Kompatibilität mit WordPress wahren.
Dein nächster Schritt hängt von deiner aktuellen Konfiguration ab. Wenn du neu anfängst, installierst du Radicle und erstellst deine erste Blade-Komponente. Wenn du ein bestehendes Theme migrierst, identifiziere sich wiederholende Markup-Muster und wandle sie Abschnitt für Abschnitt in Komponenten um. Konzentriere dich auf hochwertige Bereiche wie Navigation, Kopf- und Fußzeilen, in denen die Komponenten unmittelbar von Nutzen sind.
Wenn du ein verwaltetes WordPress-Hosting benötigst, das moderne Entwicklungsworkflows unterstützt, bietet Kinsta Funktionen, die mit Tools wie Radicle und Acorn zusammenarbeiten.