WordPress-Widgets: Refactoring, Teil 4
Wir haben eine erhebliche Menge an Änderungen am WordPress Widget Boilerplate implementiert. Wenn Sie nicht mitverfolgt haben, empfehle ich, am Anfang der Serie zu beginnen und aufzuholen.
Wenn Sie jedoch mitverfolgt haben und auch einige der Codequalitätstools ausführen, die den Status des Projekts untersuchen, werden Sie eine Handvoll Fehler in der Konsole bemerken.
Normalerweise ist dies der Punkt, an dem ich empfehle, darauf zu achten, was es teilt, und dann zu beheben, was es meldet, aber so weit sind wir noch nicht.
Einige der Fehler, die unsere Tools derzeit anzeigen, basieren beispielsweise darauf, dass wir unbenutzte Variablen haben. Das ist natürlich der Fall, weil wir noch nicht mit der Erstellung eines Widgets begonnen haben.
Aber es gibt noch ein paar konkrete Klassen, die wir implementieren müssen.
Das WordPress-Widget Boilerplate: Refactoring, Teil 4
Eines der Probleme, das im aktuellen Code immer noch besteht, ist, dass der Konstruktor des Widgets Funktionen registriert, und das ist keine gute Sache.
Der Zweck eines Konstruktors besteht darin, die Werte von Eigenschaften der Klasse festzulegen, nicht darin, irgendeine Art von Logik zu implementieren. Dies hat mehrere Gründe:
- es erzeugt eine starke Kopplung oder Abhängigkeiten zwischen den Klassen im Projekt, wenn eine bestimmte Klasse instanziiert wird,
- es führt Geschäftslogik in eine Funktion ein, die diese Funktionalität nicht enthalten soll,
- es macht es schwierig, eine Klasse isoliert zu testen.
Es gibt zwei Möglichkeiten, damit umzugehen:
- fügen Sie eine Registrierung hinzu, die wir verwenden können, um Klassen in der Anwendung zu registrieren (und sie mit so wenig Abhängigkeiten wie möglich weiterzugeben, was ich später erklären werde),
- Abonnenten erstellen, die die Geschäftslogik Hook-spezifisch handhaben können.
In den nächsten drei Beiträgen:
- sehen wir uns die Erstellung einer Registrierung an,
- wie wir es in die Bootstrap-Datei einführen können,
- und schauen Sie sich dann an, Abonnenten für jede unserer Funktionen zu erstellen (was angesichts dessen, was wir im vorherigen Beitrag getan haben, und was wir in diesem Beitrag tun, nicht allzu schwer sein sollte).
Erstellen Sie die Registrierung
Bevor Sie den Code für die Registrierung schreiben, ist es wichtig, dessen Hauptzweck zu beachten. Einfach ausgedrückt, die Klasse soll einen Verweis auf jede Klasse enthalten, die, ähm, bei ihr registriert ist.
Dies geschieht, indem eine Referenz auf ein bestimmtes Objekt an eine Funktion übergeben und auch an einen Schlüssel gebunden wird, damit wir es später leicht abrufen können.
Erste Überlegungen
Aber es gibt einige Dinge zu beachten. Zum Beispiel:
Wenn ein Objekt für einen bestimmten Schlüssel bereits in der Registrierung vorhanden ist, müssen wir eine Ausnahme auslösen. Wenn ein Benutzer versucht, ein Objekt mit einem bestimmten Schlüssel aus der Registrierung abzurufen, sollte eine Ausnahme ausgelöst werden
Natürlich muss es nicht unbedingt Ausnahmen auslösen. Stattdessen kann es auch Fehlermeldungen anzeigen, Null- oder leere Werte zurückgeben oder was auch immer Sie wählen.
Zweitens muss die Registrierung in der Lage sein, eine Liste aller darin enthaltenen Abonnenten zurückzugeben, damit sie bei WordPress registriert werden können (was wir im nächsten Beitrag sehen werden).
Dazu müssen wir jedoch sicherstellen, dass alle Abonnenten unterstützt werden, und hier kommt der Begriff des AbstractSubscriber aus dem vorherigen Beitrag ins Spiel. Das heißt, solange eine Klasse eine untergeordnete Klasse dieser Klasse ist, sind wir in Ordnung.
Erstellen der Registrierung
Planen wir also Folgendes:
- Wir erstellen eine Registry-Klasse und platzieren sie in einem Utilities-Namespace (und damit in einem Verzeichnis), falls sie in Ihrer Arbeit noch nicht vorhanden ist.
- Wir lassen die Registrierung einen Verweis auf alle ihre Objekte in einem assoziativen Array aufrechterhalten.
- Wir brauchen Methoden, um einen einzelnen Abonnenten hinzuzufügen und zu erhalten, und dann eine, um die Liste aller Abonnenten abzurufen.
Der Stub für die Klasse sieht in etwa so aus:
<?php
class Registry extends AbstractSubscriber
{
public function __construct()
{
}
public function add($id, $obj)
{
}
public function get($id)
{
}
public function getRegisteredSubscribers()
{
}
}
Als nächstes können wir die grundlegende Eigenschaft, ein Array, definieren und im Konstruktor initialisieren:
<?php
class Registry
{
private $registry;
public function __construct()
{
$this->registry = [];
}
// ...
}
Danach können wir die add-Methode erstellen. Denken Sie daran, dass ich mich in meiner Implementierung dafür entscheide, eine Ausnahme auszulösen, wenn ein Schlüssel bereits definiert ist, aber Sie müssen das nicht tun.
<?php
public function add($id, $obj)
{
if (isset($this->registry[$id])) {
throw new Exception('An object already exists for this given key.');
}
$this->registry[$id] = $obj;
}
In ähnlicher Weise gibt die get-Methode einen Verweis auf die Instanz eines Objekts zurück, das mit diesem Schlüssel identifiziert wird. Wenn der Schlüssel nicht festgelegt ist, wird eine Ausnahme ausgelöst. Wenn es gesetzt ist, aber kein Objekt existiert, geben wir null zurück.
<?php
public function get($id)
{
if (!isset($this->registry[$id])) {
throw new Exception('No object exists for the specified key.');
}
return $this->registry[$id] ?? null;
}
Schließlich benötigen wir eine Methode, um alle registrierten Abonnenten zurückzugeben. In einem zukünftigen Beitrag wird die Verwendung dafür viel offensichtlicher werden, aber beachten Sie vorerst, dass wir ein Array einer beliebigen Klasse erstellen, die eine Instanz der AbstractSubscriber -Klasse ist, und dann das gefilterte Array zurückgeben.
<?php
public function getRegisteredSubscribers()
{
$subscribers = [];
foreach ($this->registry as $object) {
if ($object instanceof AbstractSubscriber) {
$subscribers[] = $object;
}
}
return array_filter($subscribers);
}
An dieser Stelle haben wir die vollständige Klasse (komplett mit Dokumentation):
<?php
/*
* This file is part of the WordPress Widget Boilerplate
*
* (c) Tom McFarlin <tom@tommcfarlin.com>
*
* This source file is subject to the GPL license that is bundled
* with this source code in the file LICENSE.
*/
namespace WordPressWidgetBoilerplateUtilities;
use Exception;
use WordPressWidgetBoilerplateSubscriberAbstractSubscriber;
/**
* This class services as a simple container that can be used to pass objects
* around the plugin.
*
* To use this class you'd make a call to the registry by saying Registry->get(),
* then making a class to `register()` and `retrieve()` on an instance of the object.
*/
class Registry
{
/**
* @var array an array used to maintain the objects registered with the plugin
*/
private $registry;
/**
* Initializes the class by setting up the registry.
*/
public function __construct()
{
$this->registry = [];
}
/**
* Registers an object with the registry with the specified ID; however, will throw an
* exception if the ID is already referencing an object.
*
* @param string $id an ID by which the specified object will be referenced
* @param mixed $obj an instance of an object to store in the registry
*
* @throws Exception if an object already exists for the specified key
*/
public function add($id, $obj)
{
if (isset($this->registry[$id])) {
throw new Exception('An object already exists for this given key.');
}
$this->registry[$id] = $obj;
}
/**
* @param string $id the ID for the object that we wish to retrieve
*
* @throws Exception if no object exists for the specified key
*
* @return mixed a reference to the object or null
*/
public function get($id)
{
if (!isset($this->registry[$id])) {
throw new Exception('No object exists for the specified key.');
}
return $this->registry[$id] ?? null;
}
/**
* @return array all of the the Subscribers that should be registered with WordPress
*/
public function getRegisteredSubscribers()
{
$subscribers = [];
foreach ($this->registry as $object) {
if ($object instanceof AbstractSubscriber) {
$subscribers[] = $object;
}
}
return array_filter($subscribers);
}
}
Jetzt müssen wir es zum Bootstrap unseres Plugins hinzufügen.
Vor dem Bootstrap, obwohl
Wie bereits erwähnt, müssen wir dies zum Bootstrap des Plugins hinzufügen. Dazu müssen wir jedoch unseren eigenen Filter definieren, damit wir die Registrierung problemlos um den Rest des Plugins herumreichen können (wenn die Zeit dafür gekommen ist).
Bevor wir das tun, ist es jedoch wichtig sicherzustellen, dass Sie die gerade erstellte Registrierung gut im Griff haben, dass sie in das Plugin passt und dass Sie den Entwicklungszweig verfolgen, den wir bisher haben.