Objektorientiertes automatisches Laden in WordPress, Teil 1

Ich habe vor kurzem eine Serie abgeschlossen, in der ich Namespaces und automatisches Laden in WordPress behandelte. Wenn Sie mit keinem der oben genannten Begriffe vertraut sind, empfehle ich Ihnen die Serie.

Das Wesentliche dessen, was Sie erwarten können, ist folgendes:

In dieser Serie werden wir uns genauer ansehen, was PHP-Namespaces sind, warum sie von Vorteil sind und wie man sie verwendet. Dann schauen wir uns an, wie Autoloader die benötigten Dateien automatisch laden, ohne sie manuell in unseren Code laden zu müssen.

Bei der Arbeit an der Serie, insbesondere beim Autoloader, konnte ich nicht umhin, eine Reihe von Codegerüchen zu erkennen, die eingeführt wurden, als ich den Code mit Ihnen teilte.

Dies bedeutet nicht, dass der Autoloader schlecht ist oder nicht funktioniert. Wenn Sie das Plugin heruntergeladen, ausgeführt oder einen eigenen Autoloader geschrieben und geschrieben haben, wissen Sie es tut in der Tat arbeiten.

Aber in einer Serie, die sich auf Namespaces konzentriert - etwas, das Bestandteil objektorientierter Programmierung ist - konnte ich nicht anders als mich unwohl zu fühlen, wenn ich den Autoloader am Ende der Serie in seinem endgültigen Zustand belassen habe.

Versteh mich nicht falsch: Ich stehe immer noch zu der Serie, was abgedeckt wurde und das Endergebnis dessen, was wir produziert haben. Aus objektorientierter Sicht ist jedoch noch mehr Arbeit möglich. In dieser Folge werden wir das Konzept der Autoloader aus der Perspektive der objektorientierten Programmierung überdenken.

Konkret werden wir über das Konzept von sprechen:

  • Schnittstellen
  • Schnittstellenimplementierung
  • das Prinzip der Einzelverantwortung
  • und andere Prinzipien und Ideen, die den Kern der objektorientierten Programmierung bilden

Ich hoffe, dass wir unseren Autoloader bis zum Abschluss dieser Serie nicht nur in etwas verwandelt haben, das leichter zu lesen und zu lesen ist, sondern dass er auch objektorientiertere Praktiken einhält.

Nachdem dies gesagt ist, lasst uns anfangen.

Fertig machen

Wie bei fast jedem Beitrag, den ich schreibe, versuche ich gerne zwei Dinge zu tun:

  1. Definieren Sie eine Roadmap, wohin wir gehen.
  2. Geben Sie Ihnen alles, was Sie wissen müssen, um Ihre Maschine zum Laufen zu bringen.

Bevor wir mit dem Schreiben von Code beginnen, tun wir das jetzt. 

Unsere Roadmap

In den nächsten beiden Beiträgen werden wir uns einige objektorientierte Konzepte ansehen, die es uns ermöglichen werden, das Plugin zu verbessern, das wir in der vorherigen Serie erstellt haben. 

Wenn Sie keine Kopie dieses Plugins haben, können Sie eine Kopie herunterladen. Ich werde jedoch in jedem Tutorial vollständige Codebeispiele, Kommentare und Erklärungen zur Verfügung stellen. 

Die Serie wird davon ausgehen, dass Sie wissen nichts Über eines der Konzepte, die wir diskutieren werden, fangen wir von vorne an. Alles, was Sie brauchen, ist, genügend Software auf Ihrem Rechner zu haben, um eine WordPress-Version zu installieren und einen Editor zu erstellen, in dem Sie Code bearbeiten können.

Was du brauchst

Für den Einstieg benötigen Sie folgende Tools:

  • Eine lokale Entwicklungsumgebung mit wenigstens PHP 5.6.20, der Apache-Webserver und ein MySQL-Datenbankserver. Dafür ist MAMP 4 perfekt.
  • Ein Verzeichnis, in dem WordPress 4.6.1 gehostet wird.
  • Ein Texteditor oder eine IDE Ihrer Wahl, mit der Sie ein Plugin schreiben können.
  • Grundkenntnisse der WordPress Plugin API.

Nachdem Sie all dies installiert haben (und ich weiß, es scheint viel, aber die Einrichtung dauert wirklich nicht lange), müssen Sie eine Kopie des oben verlinkten Plugins installieren.

Sobald dies erledigt ist, können wir über Schnittstellen und das Prinzip der Einzelverantwortung sprechen.

Schnittstellen definiert

Abhängig von Ihrem Hintergrund in der Software können Sie, wenn Sie das Wort "Schnittstelle" hören, am Ende darüber nachdenken, was der Benutzer tatsächlich auf dem Bildschirm sieht. Sie wissen: Eine Benutzeroberfläche.

Aber wenn es um objektorientiertes Design geht, reden wir darüber überhaupt nicht. Stattdessen sprechen wir über eine Klassenschnittstelle. Dies kann normalerweise als die Klasse und die öffentlichen Methoden beschrieben werden, die andere Klassen zur Kommunikation mit ihr bereitstellen.

Gibt es eine formellere Definition? Sicher. Wikipedia bietet eines an:

In der Datenverarbeitung ist eine Schnittstelle eine gemeinsame Grenze, über die zwei separate Komponenten eines Computersystems Informationen austauschen.

Das ist eigentlich gar nicht so schlimm. Es ist allgemein genug, um auf fast jede Programmiersprache angewendet zu werden, und das ist es nicht so technisch, dass wir es nicht verstehen können.

Dann arbeiten wir wieder mit PHP. Was bietet das PHP-Handbuch zu diesem Thema??

Mit Objektschnittstellen können Sie Code erstellen, der angibt, welche Methoden eine Klasse implementieren muss, ohne festzulegen, wie diese Methoden behandelt werden.

Meiner Meinung nach ist das eine wirklich gute Definition. Es ist einfach. Es ist sprachunabhängig (meines Wissens nach) und funktioniert gut für die meisten (wenn nicht alle) objektorientierten Sprachen. Das Handbuch sagt sogar weiter:

Schnittstellen werden wie eine Klasse definiert, jedoch mit der Schnittstelle Schlüsselwort ersetzt das Klasse Schlüsselwort und ohne eine der Methoden, deren Inhalte definiert sind.
Alle in einer Schnittstelle deklarierten Methoden müssen öffentlich sein. Dies ist die Art einer Schnittstelle.

Dies sind zwei Punkte, die wir Muss Denken Sie daran, ob wir unsere eigenen Schnittstellen implementieren werden, besonders wenn es um dieses Plugin geht. Wir müssen uns nämlich Folgendes merken:

  1. Wir definieren eine Schnittstelle ähnlich wie eine Klasse, aber wir verwenden die Schnittstelle Stichwort.
  2. Die Methoden, die in einer Schnittstelle definiert sind, sind öffentlich (im Gegensatz zu sein) geschützt oder Privatgelände) weil dies die Funktionalität garantiert, auf die andere Klassen zugreifen können.

Wie kann eine Schnittstelle in einem WordPress-Projekt aussehen, bevor wir weitergehen? Hier ist ein Beispiel aus einem Projekt, an dem ich gearbeitet habe:

Der obige Code sollte klar sein, zu welchem ​​Zweck er dient, insbesondere angesichts des Kommentars oberhalb der Schnittstelle.

Wie wir alle wissen, kann WordPress zwei Arten von Assets registrieren und erfassen: Stylesheets und JavaScript-Dateien.

Da es sich bei beiden um Assets handelt, liegt es nahe, dass wir beim Erstellen von Klassen für das Stylesheet-Management oder das JavaScript-Management diese als Asset-Interface verallgemeinern?

Außerdem wissen wir, dass wir die Datei mit einer init-Methode initialisieren möchten, damit wir die angegebene Enqueue-Funktion mit der richtigen WordPress-API-Funktion verknüpfen können. Alternativ können Sie auch andere Aufgaben erledigen. Wenn dies der Fall ist, möchten Sie möglicherweise eine andere Methodensignatur zur Schnittstelle hinzufügen.

Wie auch immer, jede Klasse, die diese Schnittstelle implementiert Muss Bietet Funktionalität für die folgenden Methoden. Wie würde also eine Klasse aussehen, die diese Schnittstelle implementiert??

Hier ist ein sehr einfaches Beispiel für eine Klasse, die Stylesheets zum Verwaltungsbereich von WordPress hinzufügt:

Jetzt Wie Dies wird über PHP instanziiert und erzwungen und geht über den Rahmen dieses Tutorials hinaus. Wir werden es reichlich sehen, wenn wir mit dem Refactoring unseres Autoloaders beginnen. 

Ich möchte jedoch zeigen, dass eine Schnittstelle die öffentlichen Methoden definiert, die eine Klasse implementieren muss. Die Implementierung wird nicht definiert, sie garantiert jedoch, dass bestimmte Funktionen vorhanden sind und für Klassen von Drittanbietern öffentlich zugänglich sind.

Das Prinzip der Einzelverantwortung

Eine der Herausforderungen, wenn man über das Prinzip der Einzelverantwortung spricht, ist, dass es oft missverstanden wird, etwas zu bedeuten:

Eine Klasse (oder Funktion oder Routine) sollte nur eine Sache tun.

Aber das ist ein bisschen falsch, oder? Ich meine sogar, dass eine einfache for-Schleife mehr als eine Sache macht: Sie initialisiert einen Wert, vergleicht ihn mit Werten und iteriert dann den Wert, wenn der Körper der Schleife abgeschlossen ist.

Stattdessen heißt es im Prinzip:

Eine Klasse sollte nur einen Grund haben, sich zu ändern.

Da so viele von uns Entwicklern Google bei unserer täglichen Arbeit unterstützen, ist es meiner Meinung nach wichtig, die Quelle dieser Idee zu verstehen. Das heißt, dies kam von Onkel Bob Martin, wie er gelegentlich bekannt ist, oder von Robert Martin, der eine Reihe erstklassiger Programmierbücher verfasst hat.

Die Vorstellung, dass eine Klasse nur einen Grund hat, sich zu ändern, birgt viele Konsequenzen, nicht wahr? Hier ist ein Beispiel, das Ihnen heute von unserem Autoloader in den Sinn kommt.

Lassen Sie uns den Code überprüfen (und ich weiß, es ist keine Klasse, es ist eine Funktion, aber das Prinzip ist anwendbar):

 0; $ i--) // Liest die aktuelle Komponente des Dateiteils. $ current = strtolower ($ file_parts [$ i]); $ current = str_ireplace ('_', '-', $ current); // Wenn wir beim ersten Eintrag sind, dann beim Dateinamen. if (count ($ file_parts) - 1 === $ i) / * Wenn 'interface' in den Teilen des Dateinamens enthalten ist, * definieren Sie den $ file_name anders, damit er ordnungsgemäß geladen wird. * Andernfalls setzen Sie einfach $ file_name auf die Struktur der Klasse * Dateiname. * / if (strpos (strtolower ($ file_parts [count ($ file_parts) - 1]), 'interface')) // Ergreifen Sie den Namen der Schnittstelle aus ihrem qualifizierten Namen. $ interface_name = explodieren ('_', $ file_parts [Anzahl ($ file_parts) - 1]); $ interface_name = $ interface_name [0]; $ file_name = "interface- $ interface_name.php";  else $ file_name = "class- $ current.php";  else $ namespace = '/'. $ current $ namespace;  // Erstellen Sie nun einen Pfad zur Datei, indem Sie den Dateispeicherort zuordnen. $ filepath = trailingslashit (dirname (dirname (__FILE__)). $ namespace); $ filepath. = $ dateiname; // Wenn die Datei im angegebenen Pfad vorhanden ist, schließen Sie sie ein. if (file_exists ($ filepath)) include_once ($ filepath);  else wp_die (esc_html ("Die Datei, die versucht, unter $ filepath geladen zu werden, ist nicht vorhanden."));  

Es gibt viel von Sachen, die innerhalb dieser Funktion passieren. Wenn wir es von einem hohen Niveau betrachten, können wir sehen, dass es Folgendes tut:

  • Es bestimmt, ob PHP versucht, den Code in dieser Funktion aufzurufen.
  • Die Funktion bestimmt, ob wir eine Schnittstelle oder eine Klasse laden.
  • Der Autoloader versucht dann, die Datei einzuschließen, oder er gibt einen Fehler aus.

Wenn eine Klasse nur einen Grund für die Änderung haben soll, gibt es drei Gründe (und das ist nur auf hohem Niveau), aus denen sich diese einzelne Funktion ändern könnte. Darüber hinaus könnte der Code auch klarer sein.

Ich scheute mich nicht vor Code-Kommentaren, aber im obigen Code finden sich viele Erklärungen. Es ist in Ordnung, wenn Sie gerade erst mit dem Schreiben eines Autoloaders beginnen, aber wenn Sie sich in einem weiter fortgeschrittenen Gebiet befinden, wie wir es sind, hält das keine strengen Architekturen mehr aus.

Die zwei zusammenbringen

Hier können Schnittstellen und das Prinzip der Einzelverantwortung Hand in Hand wirken.

So wie eine Schnittstelle eine Reihe von Funktionssignaturen (oder einen Vertrag) für das, was ihre Implementierer bereitstellen, zur Verfügung stellt, kann sie sicherstellen, dass jede Klasse, die diese Schnittstelle implementiert, sich strikt an das hält, was sie definiert.

Dies wirft jedoch eine interessante Frage auf: Sollten wir mehrere Schnittstellen haben? Und die Antwort ist, dass dies von der Art der Lösung abhängt, die Sie erstellen möchten. 

In unserem Fall halte ich es für sinnvoll. 

Schließlich wollen wir einen eingehenden Klassennamen untersuchen und feststellen, ob es sich um eine Schnittstelle oder eine Klasse handelt oder ob es einen Fehler verdient. Außerdem möchten wir sicherstellen, dass die korrekte Datei im Rest des Systems enthalten ist.

Aber das geht über das Thema dieses speziellen Tutorials hinaus und eines, das wir genauer untersuchen müssen, wenn es an der Zeit ist, mehr Code zu schreiben.

Fazit

An dieser Stelle haben wir die notwendigen Konzepte behandelt, damit wir mit dem Refactoring unseres Autoloaders beginnen können. Das heißt, wir werden eine Schnittstelle einführen, die sicherstellt, dass unser Code sich daran hält, und dann sicherstellen, dass unsere Klasse (oder Klassen) und ihre jeweiligen Methoden dem Prinzip der Einzelverantwortung entsprechen.

Darüber hinaus stellen wir sicher, dass es weiterhin gut im Kontext des Plugins funktioniert, ordnungsgemäß dokumentiert ist und den WordPress-Codierungsstandards entspricht.

Wenn Sie mehr über die objektorientierte Programmierung in WordPress erfahren möchten, finden Sie alle meine vorherigen Tutorials auf meiner Profilseite. Fühlen Sie sich frei, mir auf meinem Blog zu folgen oder folgen Sie mir auf Twitter, wo ich häufig über beides spreche.

Wenn Sie nach anderen Dienstprogrammen suchen, die Sie dabei unterstützen, Ihr wachsendes Set an Tools für WordPress aufzubauen, oder beispielsweise Code, um sich mit WordPress vertraut zu machen, sollten Sie nicht vergessen, was wir in Envato Market zur Verfügung haben.

Damit ist das nächste Tutorial der Serie viel praktischer. Das heißt, wir werden Code schreiben, vorhandenen Code umgestalten und alles anwenden, was wir in diesem Tutorial gelernt haben. Zögern Sie nicht, bis dahin Feedback in den Kommentaren zu hinterlassen.

Ressourcen

  • Namespace und Autoloader-Plugin
  • Namensräume
  • Autoloading
  • Schnittstellen
  • Die WordPress Plugin-API
  • MAMP 4
  • Grundsatz der Einzelverantwortung