Update 2022-06-13:
Seien Sie gewarnt! Es stellt sich heraus, dass die Verwendung von Twig oder anderen Abhängigkeiten mit Composer in WordPress tatsächlich eine schlechte Idee ist! Das Problem ist, dass andere Plugins oder Themes möglicherweise auch dieselben Komponenten verwenden, aber in einer anderen Version – und dann können alle möglichen Konflikte auftreten! Ich empfehle daher bis auf weiteres NICHT, diesem Artikel zu folgen!
Der grundlegende Aufbau von WordPress-Plugins ist eher einfach gehalten:
Im Verzeichnis des Plugins wird als minimale Voraussetzung die Datei readme.txt
mit einer Beschreibung im Header und eine PHP-Datei für die Plugin-Initialisierung benötigt. Es ist nicht zwingend erforderlich, eigene Klassen zu implementieren, da der Code von WordPress direkt ausgeführt wird – allerdings erleichtert eine Organisation in Klassen die Lesbarkeit und Wartbarkeit erheblich.
Objektorientierter Aufbau eines WordPress-Plugins
Aufgrund der Arbeitsweise von WordPress ist der übliche Ansatz für ein objektorientieres Plugin die Implentierung einer Hauptklasse, von der zur Laufzeit eine Instanz erzeugt wird. Im Konstruktor der Klasse werden alle erforderlichen Initialisierungen ausgeführt. Es ist dabei sinnvoll, einen eigenen Namspace zu definieren, um sicherzustellen, dass die Klasse keine Konflikte mit existierenden globalen Klassen verursacht.
Für die Nutzung von register_activation_hook()
und register_deactivation_hook()
ist es notwendig, den Namen der Datei anzugeben, über die das Plugin geladen wird. Es ist daher eine gute Idee, dies als Parameter an die Hauptklasse zu übergeben, damit diese Information dort auch zur Verfügung steht.
Ebenfalls sinnvoll ist es, die Versionsnummer als Konstante (MyPlugin::VERSION
) bereitzustellen. Diese wird benötigt, wenn man mit wp_enqueue_script()
und wp_enqueue_style()
nutzt und sollte bei jedem Update des Plugin entsprechend angepasst werden.
Als Beispiel ein einfaches Plugin, was einen Shortcode bereitstellt.
In wp-content/plugins/my-plugin/readme.txt
:
=== My Plugin === Contributors: myusername Tags: images Requires at least: 5.0 Tested up to: 6.0 Stable tag: 1.0 License: GPLv2 License URI: http://www.gnu.org/licenses/gpl-2.0.html My Plugin for useful stuff. == Description == This is the detailed plugin description.
In wp-content/plugins/my-plugin/my-plugin.php
:
<?php namespace MyPlugin; defined('ABSPATH') or die(); class MyPlugin { const VERSION = '1.0'; protected string $pluginFile; public function __construct(string $pluginFile) { $this->pluginFile = $pluginFile; add_shortcode('myshortcode', array($this, 'shortCode')); } public function shortCode($atts, $content = null): string { $output = ''; // ... return $output; } } $myPlugin = new MyPlugin(__FILE__);
Der Ablauf ist hier wie folgt:
- WordPress prüft, ob das Plugin bereits aktiviert ist und führt den Code in
wp-content/plugins/my-plugin/my-plugin.php
aus. - Durch
$myPlugin = new MyPlugin();
wird eine neue Instanz der KlasseMyPlugin
erzeugt und der Konstruktor der Klasse ausgeführt, in dem der Shortcode hinzugefügt wird. - Immer wenn der Shortcode
[myshortcode]
verwendet wird, wird die MethodeMyPlugin::shortCode()
ausgeführt.
Durch die Anweisung defined('ABSPATH') or die();
am Anfang wird sichergestellt, dass der Code nur im Rahmen von WordPress ausgeführt wird – was daran erkennbar ist, dass ABSPATH
definiert ist.
Integration von Twig
Der vorgesehen Weg zur Nutzung von Twig ist die Installation mit Composer. Die Installation von Composer selbst ist in der Dokumentation beschrieben, siehe Download Composer.
Für die Installation von Twig wechselt man in einer Konsole das Verzeichnis des Plugins und führt dort folgenden Befehl aus, um Twig 3.0 zu installieren:
composer require "twig/twig:^3.0"
Damit wird Twig selbst und die dafür erforderlichen Pakete symfony/polyfilly-mbstring
und symfony/polyfill-ctype
von https://repo.packagist.org heruntergeladen. Als Ergebnis erhält man ein zusätzliches Verzeichnis vendor
für die Pakete und die beiden Dateien composer.json
und composer.lock
.
Zusätzlich legt man manuell das Verzeichnis templates
an, in dem man später die Templates für Twig ablegt. Daraus ergibt sich dann folgende Struktur:
wp-content/ plugins/ my-plugin/ templates/ vendor/ composer/ symfony/ twig/ autoload.php composer.json composer.lock my-plugin.php readme.txt
Einbinden von Twig über den Autoloader von Composer
Die notwendigen Klassen von Twig werden über den Autoloader geladen, sobald man sie mit use
anfordert. Damit das funktioniert, muss der Autoloader, den Composer im Verzeichnis vendor
angelegt hat, geladen werden.
Im Konstruktor der Plugin-Klasse wird eine Instanz von Twig erzeugt, mit der dann die Ausgabe von Templates vorgenommen wird.
Die Datei my-plugin.php
wird dafür wie folgt erweitert:
<?php namespace MyPlugin; use Twig\Loader\FilesystemLoader; use Twig\Environment; defined('ABSPATH') or die(); require(__DIR__ . '/vendor/autoload.php'); class MyPlugin { const VERSION = '1.0'; const SLUG = 'my-plugin; protected string $pluginFile; protected Environment $twig; public function __construct(string $pluginFile) { $this->pluginFile = $pluginFile; $this->twig = new Environment(new FilesystemLoader(__DIR__.'/templates')); add_shortcode('myshortcode', array($this, 'shortCode')); } } public function shortCode($atts, $content = null): string { $output = ''; // ... return $output; } } $myPlugin = new MyPlugin(__FILE__);
Verwenden von Twig-Templates
Der Aufbau von Twig-Templates ist in der Dokumentation von Twig gut beschrieben: Twig for Template Designers
Als Beispiel soll der Shortcode ein Bild anhand der angegeben ID wie folgt ausgeben:
[myshortcode id="7"]
Die Ausgabe des Shortcode wäre mit einem Twig-Template templates/shortcode.html.twig
wie folgt möglich:
<figure> <img src="{{ imageUrl }}" alt="{{ imageAlt }}" /> {% if imageCaption %} <figcaption>{{ imageCaption }}</figcaption> {% endif %} </figure>
Das kann dann zur Laufzeit im Shortcode-Handler genutzt werden:
public function shortCode($atts, $content = null): string { if (!isset($atts['id'])) { return ''; } $id = $atts['id']; return $this->twig->render('shortcode.html.twig', [ 'imageUrl' => wp_get_attachment_image_url($id, 'full'), 'imageAlt' => get_post_meta($id, '_wp_attachment_image_alt', TRUE); 'imageCaption' => wp_get_attachment_caption($id) ]); }
Mit $this->twig->render('shortcode.html.twig', ...
wird Twig dazu veranlasst, das Template in der Datei templates/shortcode.html.twig
zu verarbeiten. Die darin benötigten Variablen werden als array übergeben und stehen dann innerhalb des Template entsprechend zur Verfügung.
Ausblick
Nur für einen einfachen Shortcode mag die Verwendung von Twig übertrieben erscheinen. Es gibt aber Situationen, wo deutlich mehr HTML erzeugt werden muss, als nur ein paar Zeilen – etwa für administrative Seiten im Backend. Hier ist Twig zur Trennung von Code und UI sehr hilfreich. Templates kann man auch in kleinere Einheiten aufteilen, was die Fehlersuche vereinfacht, wenn man einer Änderung das Ergebnis nicht mehr so ist, wie erwartet.
Caching
Wenn Twig-Templates im Frontend verwendet werden, kann ein Cache sehr dabei helfen, die Leistung zu steigern. Twig compiliert jedes Template und unterstützt die Speicherung des Ergebnisses in einem Cache, so dass das Template beim nächsten Mal nicht erneut compiliert werden muss. Allerdings erfordert dies, dass ein Ordner dafür erzeugt wird, der auch beim Deaktivieren des Plugins wieder entfernt werden sollte. Dieses Thema wird in einem künftigen Artikel behandelt.
Extensions
Ebenfalls möglich ist die Einbindung eigener Twig-Extensions, siehe dazu Extending Twig. Das ist beispielsweise notwendig, wenn man die funktionen __()
oder _n()
von WordPress nutzen will, um Texte mit Übersetzungen in einem Template auszugeben. Dieses Thema wird in einem künftigen Artikel behandelt.