Bibliografische Information der Deutschen Nationalbibliothek:
Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über www.dnb.de abrufbar.
© 2015/2019 David Remer
2. überarbeitete Auflage
Herstellung und Verlag:
BoD – Books on Demand GmbH, Norderstedt
ISBN: 978-3-7494-3920-1
Für Niko.
Dir verdanke ich dieses Buch.
Dieses Buch wendet sich in erster Linie an PHP Entwickler, welche sich für WordPress interessieren und überlegen, sich auf dieses Content Management System zu konzentrieren. Dafür sprechen viele gute Gründe. Etwa ein Drittel aller Seiten im Internet laufen auf WordPress,1 die Community ist riesig, es gibt eine hervorragende Dokumentation und es macht einfach Spaß mit WordPress zu entwickeln.
Vorausgesetzt wird, dass Sie sich schon ein wenig in PHP, HTML und Javascript auskennen und eventuell auch schon die eine oder andere Webseite selbst entwickelt haben. Darüber hinaus sollten Sie auch selbst schon einmal als Anwender Erfahrungen mit WordPress gemacht haben. Falls Sie diese noch nicht gesammelt haben, ist es ratsam sich im Verlaufe dieses Buches eine WordPress Anwendung zur eigenen Anschauung lokal zu installieren. Ausgehend von diesen Voraussetzungen beschränkt sich das Buch darauf, die Beispielcodes stets nur im Hinblick auf WordPress Funktionalitäten zu kommentieren. Die Bedeutung einzelner PHP-Kommandos wird meist möglichst knapp erläutert. Natürlich kann es vorkommen, dass Sie einzelne PHP-Befehle nicht kennen. Sollten sich Ihnen diese nicht aus dem Zusammenhang erschließen, sei Ihnen die PHP Dokumentation ans Herz gelegt.2 Ziel des vorliegenden Buches ist, Ihnen aufbauend auf Ihren Kenntnissen schnell den Weg zur Entwicklung mit WordPress zu ebnen. Das Buch soll Sie in die verschiedenen Konzepte von WordPress eingeführen und verschiedene WordPress-spezifische Funktionen erläutern. Nach der Lektüre sollten Sie erstens in der Lage sein, selbstständig Plugins oder Themes für beinahe alle Herausforderungen zu schreiben und zweitens fähig sein, für Probleme, deren Lösungen hier nicht besprochen wurden, schnell Lösungen zu finden.
Viele Codebeispiele werden von kleineren Plugins begleitet. Unter https://github.com/websupporter/wordpress-fuer-entwickler finden Sie ein Repository, welches sämtliche Beispiele enthält. Im Buch finden Sie dann unterhalb der Codeblöcke den Pfad zu der jeweils besprochenen Datei.
Nachdem wir kurz einige Voraussetzungen sowie Tipps und Tricks besprochen haben, werden Sie in die grundlegenden Konzepte von WordPress eingeführt.
Schon im Anschluss daran entwickeln wir ein erstes kleines Plugin und sehen uns an, wie man ein Widget für Sidebars erstellt. Wir konzentrieren uns dabei vor allem auf Plugins, da vor allem diese der Funktionserweiterung dienen, während Themes stärker auf das Layout einer Seite ausgerichtet sind. Nichtsdestotrotz benötigt auch die Entwicklung von Themes PHP, weshalb wir uns nach unserem ersten Plugin und Widget zunächst auf die Struktur von Themes konzentrieren werden.
Danach machen wir uns mit der WordPress Datenbank vertraut und lernen, wie man mit WordPress Datenbankinformationen erhalten, beziehungsweise manipulieren kann. Im Verlaufe dieses Buches wird sich zeigen, dass Sie normalerweise kaum auf der Ebene der Datenbank operieren müssen, da WordPress eine Vielzahl von Befehlen bereithält, welche diese Aufgaben für Sie übernehmen.
Nachdem wir uns mit der Datenbank vertraut gemacht haben, können wir nun endlich ans Eingemachte gehen und einzelne Konzepte, auf denen WordPress basiert, näher erörtern. Dazu gehört der Loop, benutzerdefinierte Felder, sowie Taxonomien und Posttypen. Mit Hilfe des WordPress Loops strukturiert WordPress die Ausgabe von Beiträgen und anderen Inhalten auf der Webseite. Benutzerdefinierte Felder dienen dazu, Beiträge mit Meta-Informationen anzureichern. Sie stellen gerade für die Plugin-Entwicklung eine zentrale Schnittstelle dar. Wir werden deshalb ein Beispielplugin erstellen, mit dessen Hilfe Beiträge um Längen- und Breitengrade ergänzt werden können, um aus diesen eine Landkarte zu generieren. Taxonomien sind das Klassifikationsschema von WordPress. Mit Hilfe dieses Konzepts werden Beiträge Kategorien zugeordnet und verschlagwortet. Sie lernen, wie man mit diesen Schemata arbeiten und auch selbst neue Taxonomien anlegen kann. Posttypen wiederum sind bestimmte Arten von Seiten. So gibt es beispielsweise den Typ 'post'
, welcher ganz generell Blogbeiträge bezeichnet. Der Typ 'page'
repräsentiert statische Seiten, wie Impressums- oder Kontaktseiten. In dem Kapitel „Eigene Posttypen entwickeln“ werden Sie lernen, wie Sie selbst solche Typen generieren können, um beispielsweise für einen Onlineshop Produkte anlegen zu können.
Das nächste Kapitel beschäftigen sich damit, herauszufinden welche Seite gerade angezeigt wird. Mit Hilfe simpler konditionaler Abfragen können Sie so herausfinden, ob gerade eine einzelne Beitragsseite oder aber das Archiv einer Kategorie dargestellt wird. Sie werden schnell lernen, dass diese Abfragen Gold wert sind. Danach besprechen wir, wie man dem Administrator einer WordPress-Seite die Möglichkeit an die Hand gibt, ein Menü zu erstellen und auf der Seite darzustellen.
Wenn Sie sich bis hierhin durchgeschlagen haben, verfügen Sie bereits über ausreichende Kenntnisse, um recht komplexe Anwendungen zu realisieren. Solche komplexen Anwendungen machen es immer wieder erforderlich, dass beispielsweise der Administrator bestimmte Einstellungen für ein Plugin ändern und speichern kann. Wir widmen uns deshalb zunächst dem Thema, wie man mit WordPress auf der Ebene der Programmlogik überhaupt Einstellungen speichern und abrufen kann, um daraufhin in die Benutzerverwaltung einzusteigen. Darüber hinaus werden Sie mit dem WordPress Nonces Konzept vertraut gemacht, um die Sicherheit Ihrer Anwendung zu erhöhen und schließlich werden Sie im Kapitel „Den Admin erweitern“ lernen, wie Sie dem Administrator, oder einem anderen registrierten Benutzer, eine Oberfläche zur Verfügung stellen können, in der er Ihr Plugin oder Ihr Theme modifizieren kann.
Seit WordPress 5.0 hat „Gutenberg“, der neue Editor, Einzug in WordPress gehalten. Im Administrationskapitel besprechen wir die Möglichkeit diesen zu erweitern und Blöcke zu entwickeln ab Seite →. WordPress ist bekannt für seine „Backwards-Compatibility“, also dafür, dass Versionsänderungen nur äußerst selten bedeuten, das man ein Plugin aktualisieren muss. Im Falle von „Gutenberg“ zeichnet sich ab, dass dies zumindest für die Zeit, bis das Projekt komplett implementiert ist, etwas holpriger werden könnte.3 Natürlich wird das vorliegende Buch entsprechend aktualisiert werden. Um sich auf dem Laufenden zu halten sei ein Blick in das Handbuch unter https://wordpress.org/gutenberg/handbook/ dennoch ans Herz gelegt.
Damit haben Sie nun endgültig einen umfangreichen Blick auf die Möglichkeiten erhalten, welche WordPress Ihnen als Entwickler bietet. Es stellt sich die Frage, wie Sie Ihr Plugin einem großen Kreis von Anwendern zur Verfügung stellen können. Wir werden uns deshalb mit der Internationalisierung Ihrer Anwendung beschäftigen, das heißt, wie Sie Ihr Plugin befähigen in verschiedene Sprachen übersetzt zu werden.
Abschließend führen wir noch kurz in verschiedene weitere Konzepte ein. Sie lernen mit der REST API von WordPress zu arbeiten, erfahren, wie WordPress Cronjobs funktionieren und wie man auch objektorientiert mit WordPress programmieren kann. Sie werden in die Walker-Klasse zur strukturierten Ausgabe hierarchischer Elemente eingeführt, erfahren, wie Sie mit der WordPress eigenen HTTP-API arbeiten und wie Sie sich das Rewrite-System zu Nutze machen können.
1. Siehe https://w3techs.com/technologies/details/cm-wordpress/all/all
2. http://php.net/manual/de/
3. Weitere Informationen zur aktuellen Roadmap von WordPress finden Sie unter https://de.wordpress.org/about/roadmap/
In diesem Kapitel wollen wir nur kurz verschiedene Tipps und Empfehlungen aussprechen, welche Ihnen während Ihrer Arbeit mit WordPress hilfreich sein werden.
Wie eigentlich immer, wenn es um die Entwicklung von Webseiten geht, sollten Sie Ihre Anwendung auch bei WordPress lokal entwickeln. Dazu müssen Sie zunächst eine Serverumgebung auf Ihrem Computer einrichten. Für Windows hat sich hier über die Jahre XAMPP (https://www.apachefriends.org/de/) als eine schnelle und einfache Möglichkeit etabliert, eine solche Umgebung aufzusetzen. Wenn Sie das Control Panel öffnen und sowohl Apache als auch MySQL starten, können Sie loslegen. Geben Sie nun in Ihrem Browser http://localhost/ ein, erreichen Sie das Root-Verzeichnis Ihres Servers, unter einer Windows Installation ist dies meist C:/xampp/htdocs/.
Laden Sie sich nun die neuste Version von WordPress herunter4 und entpacken Sie diese in das htdocs/ Verzeichnis. Nachdem Sie nun alle Dateien entpackt haben, müssen Sie noch eine Datenbank bereitstellen, mit welcher WordPress arbeiten kann. Wenn Sie auf http://localhost/phpmyadmin gehen, können Sie dort eine Datenbank anlegen. Anschließend wechseln Sie in Ihrem Browser auf http://localhost/wordpress und folgen den Installationsanweisungen. Sobald Sie dies getan haben, verfügen Sie über ein komplett installiertes WordPress System auf Ihrem Rechner mit dem Sie arbeiten können.
Im Internet finden Sie zahlreiche wunderbare Dokumentationen, Tutorials, Blogs und Code-Snippets rund um WordPress. Die wichtigste Anlaufstelle für Sie als Programmierer ist dabei sicherlich das WordPress Handbuch, welches Sie unter der Adresse https://developer.wordpress.org/ finden. Natürlich können Sie nicht immer alle Funktionen und deren Parameter im Kopf behalten. Sie werden sicherlich die wichtigsten kennen, andere aber eher rudimentär und manche – auch nach der Lektüre dieses Buches – überhaupt nicht. Im Codex, der Dokumentation von WordPress, werden Sie fündig werden! Vergessen Sie Google nicht! Umschreiben Sie – am besten in Englisch – was Sie suchen und ergänzen Sie „WordPress“. Sie werden in beinahe 100% der Fälle fündig, schließlich hat irgendjemand sicherlich schon einmal Ihre Frage in irgendeinem Forum gestellt.
Womit wir bei einer der wichtigsten Quelle wären. Neben den Foren von WordPress (http://de.wordpress.org/support ist das zentrale deutschsprachige WordPress-Forum und https://wordpress.org/support/ das zentrale englischsprachige) ist vor allem WordPress StackExchange (http://wordpress.stackexchange.com/) ein unverzichtbares Forum, wenn es um Fragen rund um die Entwicklung mit WordPress geht. Seiten wie WP Beginner (http://www.wpbeginner.com) sind vor allem für Anfänger immer wieder eine Quelle für Tipps und Tricks. Aber auch im deutschsprachigen Raum finden sich viele interessante Blogs rund um WordPress. Der bekannteste Blog für Webworker ist dabei sicherlich Dr. Web (http://drweb.de). Dr. Web ist zwar nicht auf WordPress spezialisiert, doch wird hier auch immer wieder über WordPress gebloggt. Hervorragende Quellen für deutschsprachige WordPress-News sind KrautPress (https://krautpress.de/) oder auch der Blog von Florian Brinkmann (https://florianbrinkmann.com/). Beide bloggen regelmäßig über WordPress Neuerungen, Themes, Plugins und alles rund um WordPress. Auch der Perun-Blog (http://www.perun.net/) des Autoren und WordPress-Spezialisten Vladimir Simovic sollten Sie aufsuchen. Unter den Newslettern ist vor allem der WP-Letter (https://wpletter.de/) zu erwähnen.5 Im englischsprachigen Raum sei Ihnen vor allem WP Tavern (http://wptavern.com/) ans Herz gelegt. Ich werde hier nun allerdings nicht damit beginnen, all die großartigen Blogs aufzuführen, sondern verweise Sie hier an die Suchmaschine Ihres Vertrauens. Sie werden sehen, die WordPress Community ist riesig!
Die Community von WordPress ist auch deshalb so riesig, weil tausende von Plugin-Entwicklern rund um den Globus WordPress täglich um neue Funktionen bereichern. Genau zu dieser Gruppe werden auch Sie schon sehr bald gehören.
Damit stellt sich jedoch ein besonderes Problem. Überlegen Sie gut, wie Sie Ihre Funktionen und globalen Variablen (falls Sie welche benutzen) benennen. Wenn Sie die zentrale Funktion Ihres Plugins init()
nennen, wundern Sie sich nicht, wenn Sie häufig Beschwerden bekommen, das Ihr Plugin nicht funktioniert, weil schon ein anderes, aktives Plugin, eine Funktion namens init()
besitzt. Wenn Ihre Software nach wie vor auch unter PHP 5.2 laufen soll, suchen Sie sich einen originellen Präfix, dem Sie jeden Funktionsnamen voranstellen. Manche Entwickler arbeiten dabei sogar mit Zahlenketten und nennen Ihre Funktion beispielsweise wp12345_init()
. Besser ist es natürlich, mit Namespaces zu arbeiten, welche mit PHP 5.3 eingeführt wurden. Sehen Sie auf Seite →, wie Sie Ihre Funktionen entsprechend im WordPress System registrieren.
Die ganze Idee von Themes und Plugins ist letzten Endes, dass Sie mit WordPress ein System haben, welches Sie beliebig erweitern können, ohne jemals die System-Dateien selbst ändern zu müssen. Dadurch können Administratoren das System ständig aktualisieren, ohne dass Ihre Software davon betroffen wäre. Änderungen, die Sie an den System-Dateien vornehmen werden hingegen mit dem nächsten WordPress Update überschrieben. Wenn Sie das Gefühl haben, es geht nicht anders, dann liegen Sie schlicht falsch. Es gibt immer eine Lösung, welche die System-Dateien unberührt lässt.
Die Aufforderung die System-Dateien nicht zu ändern heißt aber nicht, diese nicht gründlich zu studieren. Sie werden auf jede Menge Action- und Filter-Hooks stoßen, die nirgends richtig dokumentiert sind, aber vielleicht gerade für Ihr Problem die Lösung darstellen. Wenn Sie das Gefühl haben, jetzt müssten Sie die System-Dateien ändern, lesen Sie diese erst einmal. Die Lösung finden Sie meistens genau darin. Dieses Buch ist als Einstieg in die WordPress-Programmierung gedacht. Einige Schnittstellen werden hier – obwohl Sie für eines Ihrer Projekte durchaus zentral sein könnten – überhaupt nicht besprochen. Neben den Ressourcen, welche WordPress auf wordpress.org bereitstellt sind die Core-Files natürlich die erste Quelle, um zu verstehen, wie das System, in welchem Sie arbeiten, funktioniert.
4. Download: https://de.wordpress.org/
5. Eine kurarierte Liste finden Sie auch unter https://de.wordpress.org/der-planet-feed/planet-feed-websites/.
Wenn Sie für WordPress entwickeln sind die ersten beiden Konzepte, welche Sie auseinanderhalten müssen „Plugin“ und „Theme“. Sie können entweder ein Plugin entwickeln oder ein Theme. Als grobe Richtlinie kann man sagen, Plugins sollen die Funktionalität einer Webseite erweitern, während Themes das Aussehen einer Webseite definieren. Als WordPress Administrator kann man also immer nur ein Theme aktivieren, während man andererseits beliebig viele Plugins aktiviert haben kann.
Wenn Sie also beispielsweise eine Datumsanzeige entwickeln möchten, welche immer die aktuelle Uhrzeit auf dem Blog einblendet, so handelt es sich hierbei eher um eine funktionale Erweiterung des Systems als um ein grundlegendes Layout. Insofern sollten Sie hierfür ein Plugin entwickeln. Möchten Sie hingegen WordPress die Möglichkeit geben, so auszusehen, wie Pinterest, dann sollten Sie ein Theme entwickeln. Diese Entscheidung ist grundlegend, denn sie beeinflusst nicht nur, wo Sie am Ende Ihre Dateien abspeichern müssen, sondern mit dieser Entscheidung fallen auch unterschiedliche Design-Konzepte zusammen. Nur ein Beispiel (wir werden darauf in einem späteren Abschnitt ausführlicher zu sprechen kommen): Wenn Sie ein Theme entwickeln, können Sie unterschiedliche Seitentemplates festlegen. Jedes Seitentemplate ist dann eine eigene PHP-Datei. Entwickeln Sie ein Plugin, können Sie solche Templates nicht festlegen. Auch werden Sie je nachdem, ob Sie ein Plugin oder ein Theme entwickeln verschiedene Befehle gebrauchen. So werden Sie sehr schnell den Befehl plugins_url()
benötigen, wenn Sie ein Plugin schreiben. Dieser Befehl gibt Ihnen die URL zu Ihrem Plugin zurück. plugins_url()
funktioniert allerdings nicht bei Themes, wo Sie froh über get_template_directory_uri()
sein werden.
Ruft man eine WordPress-Seite auf, so aktiviert sich das gesamte System und läuft verschiedene Etappen durch. Das System wird initialisiert, der Header ausgegeben, der Content, die Sidebars, der Footer der Seite und so weiter. Mit Hilfe sogenannter „Hooks“ kann der Entwickler sich in diese verschiedenen Prozesse einklinken und seinen eigenen Code ausführen.
Es gibt zwei Typen von Hooks: Actions und Filter. Actions werden bei bestimmten Ereignissen, zum Beispiel dem Speichern eines neuen Posts ausgeführt. Durch sogenannte Filter werden Daten durchgeleitet, beispielsweise um danach ausgegeben zu werden.
Adam Brown führt auf seiner Webseite eine Liste aller Hooks,6 welche von WordPress ausgeführt werden. Hier listet er über 1.800 verschiedene Filter- und Actionhooks auf, welche zu bestimmten Zeitpunkten im System aktiviert werden..
Doch, wie funktioniert ein Hook jetzt im Allgemeinen? Nehmen wir uns zunächst den wohl berühmtesten Filter vor: 'the_content'
. Über diesen wird der Inhalt eines Posts (nicht der Titel, sondern nur der Text) gefiltert. Das System holt also den Inhalt aus der Datenbank und bevor WordPress diesen Inhalt nun auf dem Bildschirm des Benutzers ausgibt, wird er mit Hilfe von 'the_content'
gefiltert. Ihr Plugin7 kann sich nun in diesen Filter einklinken und den Inhalt verändern, bevor er ausgegeben wird:
<?php
add_filter
( 'the_content', 'change_content'
);
function change_content
( $content
){
$add = '<p>Abruf des Blogposts: ';
$add .= date
( 'd.m.Y h:i:s', time
() ) . '</p>';
$content = $add . $content;
return $content;
}
plugins/3-the-content/code.php
Zunächst klinken wir uns mit add_filter()
in den Prozess ein. Dazu müssen wir mindestens zwei Parameter angeben: In welchen Filter wir uns einklinken ('the_content'
) und wie die Funktion heißt, die sich in den Filter einklinkt (in unserem Beispiel: change_content()
). Man kann noch zwei weitere Parameter an add_filter()
übergeben: Die Priorität und die Anzahl der Argumente, welche Ihre Funktion akzeptiert. Da mehrere Plugins auf den gleichen Filter zugreifen können, kann man mit dem dritten Parameter die eigene Priorität bestimmen und sich so in der Schlange nach vorne oder nach hinten einreihen. Die normale Priorität ist 10, je kleiner die Zahl (dabei handelt es sich um einen Integer) ist, desto früher wird der eigene Filter ausgeführt. Über die akzeptierten Argumente kann man festlegen, wie viele Argumente die eigene Funktion als Parameter akzeptiert. Der Standard ist hier 1
. Je nachdem welcher Hook ausgeführt wird, können aber auch mehr als ein Argument übergeben werden. Filter übergeben dabei im ersten Parameter immer den Wert, welcher gefiltert werden soll. Die weiteren Parameter geben Ihnen Informationen über den aktuellen Kontext.
Action Hooks funktionieren ganz ähnlich. Statt mit add_filter()
werden diese mit add_action()
aufgerufen:
<?php
add_action
( $hook, $function, $priority, $args
);
Wenn Sie Namespaces benutzen, so sollten Sie dies natürlich berücksichtigen. Statt einfach den Funktionsnamen zu registrieren, müssen Sie den kompletten Pfad zu Ihrer Funktion angeben:
<?php
namespace Websupporter\AwesomePlugin;
add_filter
( 'the_content', __NAMESPACE__ . '\change_content'
);
function change_content
( $content
){
$add = '<p>Abruf des Blogposts: ';
$add .= date
( 'd.m.Y h:i:s', time
() ) . '</p>';
$content = $add . $content;
return $content;
}
Statt __NAMESPACE__
können Sie natürlich auch den Namespace ausschreiben: \Websupporter\AwesomePlugin
. Dies ist sinnvoll, wenn Sie auf eine Funktion in einem anderen Namensraum referenzieren müssen.
Eine gute Übersicht über Action- und Filterhooks bietet natürlich auch der WordPress Codex,8 den man bei solchen Fragen immer wieder aufsuchen sollte.
Ein weiteres interessantes Konzept, gerade für Plugin Entwickler, sind die sogenannten Shortcodes,9 über welche WordPress seit Version 2.5 verfügt. Shortcodes sind im Wesentlichen Makro Codes, welche der Autor über den Texteditor eingeben kann. Gibt man beispielsweise den Shortcode [gallery]
im Editor ein, so wird an dieser Stelle in der Folge eine Galerie dargestellt. Shortcodes werden mit Hilfe von add_shortcode()
erzeugt.
So können Sie ein Plugin erstellen, welches einen neuen Shortcode für den Benutzer bereithält. Sagen wir, Sie möchten einen Shortcode bereitstellen, welcher das aktuelle Datum im Text ausgibt:
<?php
add_shortcode
( 'angesehen', 'mein_shortcode'
);
function mein_shortcode
( $attr
){
$string = '<p>Angesehen am: ';
$string .= date
( $attr
['format'
], time
() );
$string .= '</p>';
return $string;
}
plugins/3-first-shortcode/code.php
Schreiben Sie nun einen Blogpost und geben dort den Shortcode [angesehen format=“Y-m-d H:i:s“]
an, so wird an dieser Textstelle nun der Shortcode ausgeführt. Sie sehen auch schon eine sehr interessante Möglichkeit bei Shortcodes: Der Autor kann im Texteditor Attribute übergeben! In diesem Fall gibt der Autor das Datumsformat an, indem er format="Y-m-d H: i:s"
angibt. Er könnte also beispielsweise auch format=“d.m.Y H: i“
angeben und würde so statt 2014-12-01 16:41:23 folgende Datumsausgabe sehen: 01.12.2014 16:41
Doch Shortcodes können noch mehr! Sagen wir, wir wollen einen Shortcode bereitstellen, der einen bestimmten Textabschnitt in einer vom Autoren bestimmten Farbe hinterlegt. Der Autor soll einfach sagen können von hier bis da, da will ich einen roten Hintergrund:
Wir definieren also einen Shortcode [hintergrund]
, der das Attribut 'farbe'
kennt, in welcher der Autor eine HEX-Farbe definieren kann. Jetzt kann man Shortcodes auch ganz ähnlich verwenden wie HTML-Tags, man kann sie öffnen und schließen:
[hintergrund farbe="#f00"
]
Dieser Text soll rot werden
[/hintergrund
]
Man schließt einen Shortcode genauso wie man HTML-Tags schließt. Sehen wir uns nun an, wie unsere Shortcode Funktion sich ändern muss, um hier zu funktionieren:
<?php
add_shortcode
( 'hintergrund', 'mein_shortcode'
);
function mein_shortcode
( $attr, $content
){
$string = '<span style="background-color:'.$attr
['farbe'
].'">';
$string .= $content;
$string .= '</span>';
return $string;
}
plugins/3-background-shortcode/code.php
Unsere Funktion mein_shortcode()
akzeptiert diesmal neben dem $attr
-Parameter noch einen zweiten Parameter: $content
. Diese Variable enthält alles zwischen [hintergrund]
und [/hintergrund]
. Nun können wir unseren $content
also mit einem <span>
umschließen und diesem eine Hintergrundfarbe zuweisen. Wir haben damit schon einen ersten guten Überblick über WordPress und sollten nun einfach beginnen ein erstes Plugin zu entwickeln. In einem späteren Kapitel werden wir tiefer in die Datenbank Struktur, in Posttypen, benutzerdefinierte Felder und Taxonomien einsteigen, um schließlich die ganze Power von WordPress ausnutzen zu können.
6. http://adambrown.info/p/wp_hooks/hook
7. Auf Seite 27 erfahren Sie, wo Sie diesen Code abspeichern müssen, und welche Vorkehrungen Sie treffen müssen, damit aus dem Code ein Plugin wird, welches WordPress ausführen kann.
8. http://codex.wordpress.org/Plugin_API/Filter_Reference
9. Seit WordPress 5.0 setzt man in vielen Fällen, wo man zuvor Shortcodes eingesetzt hatte, heute lieber auf die Entwicklung sogenannter Blöcke. Mehr zur Entwicklung von Blöcken für den Editor erfahren Sie auf Seite 247.
Es ist an der Zeit für unser erstes Plugin. Im ersten Schritt werden wir zunächst die Grundstruktur eines Plugins kennenlernen. Im Zweiten dann die Funktionalität von WordPress um einen Shortcode erweitern. Mit Shortcodes ist das so eine Sache. WordPress ist eine große Community und zu fast jeder Frage oder Funktion gibt es die unterschiedlichsten Auffassungen. Manche lieben Shortcodes und nutzen diese extensiv, bis man im Editor vor lauter Shortcodes den Text nicht mehr lesen kann. Andere verteufeln Shortcodes gerade deswegen und verweisen seit WordPress 5.0 darauf, dass man für die meisten Shortcode Anwendung besser auf selbst definierte Blöcke zurückgreifen sollte.10 Mit derartigen Überzeugungen – ich selbst verwende sie eher zurückhaltend – wollen wir uns hier allerdings erst einmal nicht aufhalten. Shortcodes haben nämlich einen großen Vorzug für uns Programmierer: Sie sind schnell mal entwickelt und eignen sich daher wunderbar, um in die Programmierung von Plugins einzusteigen. Damit beginnen wir jetzt.
Ein WordPress Plugin muss über eine bestimmte Grundstruktur verfügen, um von WordPress erkannt zu werden. Sie kennen sicher schon die Darstellung von Plugins in Ihrem WordPress Admin:
Sie sehen einen Namen, eine Beschreibung, die Versionsnummer, den Autoren, erhalten einen Link zur Plugin Webseite und so weiter. In der WordPress-Grundeinstellung sind alle Plugins in einem Ordner zusammengefasst, welchen Sie unter /wp-content/plugins finden. Meist sind diese dort in einem eigenen Unterordner platziert. Wenn Sie sich nun also daran machen ein neues Plugin zu entwickeln, müssen Sie zunächst ein neues Verzeichnis anlegen. Überlegen Sie sich am besten einen eigenständigen Namen, damit Ihr Plugin nicht möglicherweise irgendwann mit einem anderen kollidiert.
In unserem Beispiel werden wir nun einen Shortcode erzeugen, der einen Textabschnitt verbirgt, welcher mit Hilfe von Javascript sichtbar wird, sobald der Leser auf einen „Lesen Sie mehr“-Text klickt. Wir nennen dieses Plugin „Inline Read More“ und unser Verzeichnis inline-read-more/. In diesem Verzeichnis legen wir nun auch eine PHP Datei ab, welche wir inline-read-more.php nennen. Dies ist unsere Root-Datei. Um von WordPress richtig erkannt zu werden, benötigt diese Datei nun einen ganz bestimmten Header, der von WordPress ausgelesen werden kann:
<?php
/**
* Plugin Name: Inline Read More
* Plugin URI: http://www.plugin-url.com
* Description: Beschreibung
* Version: 1.0
* Author: Websupporter
* Author URI: http://www.websupporter.net/
* License: GPL2
*/
Dies sind die gängigsten Angaben, welche hinterlegt werden können. Sie müssen einen Pluginnamen angeben, eine URL zum Plugin, eine Beschreibung, eine Version, den Autoren, die URL zur Webseite des Autoren, sowie eine Lizenz. Aus diesen Angaben wird dann die Plugindarstellung aus Abbildung 4 generiert.
Um ein solides Plugin zu programmieren, müssen Sie WordPress anweisen, Fehlermeldungen auszugeben. Normalerweise unterdrückt WordPress PHP-Fehler, was natürlich gute Praxis für offen zugängliche Webseiten ist, denn damit verhindern Sie, dass jeder sofort sehen kann, wo Schwachstellen in Ihrer Webseite sein könnten.
Zum Entwickeln eines Plugins oder Themes sollten Sie sich jedoch ständig jeden noch so kleinen Fehler ausgeben lassen, um ihn sofort zu beseitigen, so dass es möglichst zu keinen Problemen kommt. Im Root-Verzeichnis von WordPress finden Sie die wp-config.php. In ihr werden zentrale Einstellungen, wie der Zugang zur Datenbank und ähnliches vorgenommen. Dort sollten Sie folgende Konstante definieren: define('WP_DEBUG', true);
. Ab sofort werden in dieser WordPress Version Fehler angezeigt und nicht mehr unterdrückt.
Fehleranfällige Plugins sind immer wieder einer der Gründe, weshalb eine WordPress-Anwendung gehackt werden kann. Im Internet finden Sie zahlreiche Tipps und Hinweise, wie Sie Ihr Plugin sicherer machen können. Dazu gehört in erster Linie natürlich immer wieder die eingehenden Daten zu validieren. Ein weiterer, recht simpler Trick ist es, den direkten Zugriff auf Ihr Plugin zu verhindern. Ihr Plugin liegt ja in dem Plugin-Verzeichnis und der Pfad zu den einzelnen Dateien ist relativ schnell herausgefunden, insbesondere, wenn Sie Ihr Plugin über das Repository zur Verfügung stellen. Verhindern Sie deshalb den direkten Zugriff auf diese PHP-Dateien und stellen Sie sicher, dass diese nur innerhalb von WordPress zur Anwendung kommen. Ihre PHP-Dateien können Sie vor einem außerhalb von WordPress stattfindenden Zugriff mit Hilfe des folgenden Codes schützen:
<?php
if
( ! defined
( 'ABSPATH'
) ) exit;
Die Konstante ABSPATH
wird zentral in der wp-load.php definiert und bezeichnet den Root-Pfad der Anwendung. Ist diese nicht definiert, so wurde Ihr Script nicht von WordPress sondern von außerhalb aufgerufen. In diesem Fall sollten Sie das Script einfach beenden.
Doch machen wir uns nun endlich an die Entwicklung unseres Shortcodes. Wir haben im vorherigen Abschnitt schon gelernt, wie man einen neuen Shortcode anlegt. Im ersten Schritt müssen wir dazu den Shortcode definieren. Der Autor soll in der Lage sein mit dem Shortcode [read_more_inline]
einen Textabschnitt zu definieren, welcher erst aufscheint, wenn der Leser einen bestimmten „Link“-Text geklickt hat. Diesen soll der Autor natürlich auch festlegen können, weshalb wir das Attribut 'title'
verwenden. Ein vollständig konfigurierter Shortcode soll demnach wie folgt aussehen:
[read_more_inline title="Mehr"]
Dieser Text ist verborgen.
[/read_more_inline]
Im ersten Schritt werden wir also unseren Shortcode definieren:
<?php
/**
* Plugin Name: Inline Read More
* Plugin URI: http://www.websupporter.net/plugin/
* Description: Beschreibung des Plugins
* Version: 1.0
* Author: Websupporter
* Author URI: http://www.websupporter.net/
* License: GPL2
*/
add_shortcode
( 'read_more_inline', 'rm_inline'
);
function rm_inline
( $attr, $content
){
$string = '<span class="read_more_inline">';
$string .= '<a class="read_more_title">';
$string .= $attr
['title'
];
$string .= '</a><span class="read_more_body">';
$string .= $content;
$string .= '</span></span>';
return $string;
}
plugins/4-read-more-link/index.php
Wir erzeugen also ein span. read_more_inline
, welches ein span.read_more_title
mit dem Titel enthält und ein span.read_more_body
, welches den Inhalt enthält, der allerdings zunächst verborgen sein wird. Was natürlich vollkommen fehlt ist die Funktionalität, welche wir über Javascript herstellen möchten. Wir könnten nun einfach den Javascript Code in der $string
-Variablen mit übergeben. Dies hätte allerdings einige Unannehmlichkeiten zur Folge und deshalb werden wir hier lieber über einen Hook ein neues Script registrieren. Außerdem fehlt uns ein schönes Stylesheet, mit dem wir unseren . read_more_body
verbergen können. Statt also Inline-Styles und -Scripte zu verwenden werden wir den Action Hook 'wp_enqueue_scripts'
nutzen. Über diesen Hook kann man seine eigenen Stylesheets und Scripte in WordPress einhaken. Das hat einige interessante Aspekte, die wir an folgendem Beispiel erörtern werden:
<?php
add_action
( 'wp_enqueue_scripts', 'irm_scripts'
);
function irm_scripts
() {
$plugin_url = plugins_url
( '/', __FILE__
);
wp_enqueue_style
(
'irm-style',
$plugin_url . 'style.css'
);
wp_enqueue_script
(
'irm-script',
$plugin_url . 'script.js',
array
( 'jquery'
),
'1.0.0',
true
);
}
plugins/4-read-more-link/enqueue-scripts.php
So definieren wir zunächst die Funktion irm_scripts()
, welche im Action Hook 'wp_enqueue_scripts'
ausgeführt wird. In dieser Funktion ermitteln wir als erstes den Pfad zu unseren Scripten. Das ist für gewöhnlich wp-content/plugins/pluginname/. Doch dieser Verzeichnispfad kann auch ein anderer sein, je nachdem wie WordPress konfiguriert wurde. Deshalb sollte man diesen Pfad auf keinen Fall „hard coden“, sondern auf die Funktion plugins_url()
zurückgreifen, welche die URL zum Plugin ausgibt.
Diese Funktion gibt die absolute URL zum Plugin aus und akzeptiert zwei Parameter, welche allerdings optional sind. Normalerweise nimmt man diesen Befehl, um die URL zu einer bestimmten Datei unseres Plugins, ein Script, ein Bild oder ein Stylesheet, zu bestimmen. Mit dem ersten Parameter kann man den relativen Pfad zu dieser Datei von plugins/-Verzeichnis aus angeben. Mit der PHP Konstanten __FILE__
kann man – im zweiten Parameter – den ersten relativen Pfad in Abhängigkeit der ausführenden PHP-Datei erstellen. Ein Beispiel: Nehmen wir an, Sie haben in Ihrem Plugin das Unterverzeichnis inc/ und in diesem befinden sich eine PHP Datei styles.php, sowie ein weiteres Unterverzeichnis css/. Dort existiert eine style.css. Den Pfad zu dieser style.css können Sie in der styles.php nun wie folgt ermitteln:
<?php
echo plugins_url
( '/css/style.css', __FILE__
);
Doch kehren wir zu unserem vorherigen Script zurück, in welchem wir unser Stylesheet und unser Javascript registrieren möchten. Dort nutzen wir plugins_url()
, um die URL zu unserem Plugin in die Variable $plugin_url
zu laden.
Anschließend benutzen wir den Befehl wp_enqueue_style()
, um unser Stylesheet zu registrieren, und anschließend registrieren wir unser Script mit wp_enqueue_script()
. Natürlich werden wir später die entsprechenden Dateien auch erstellen und einbinden.
In unserem Beispiel verwenden wir ausschließlich die enqueue-Befehle. Der Vollständigkeit halber muss allerdings erwähnt werden, dass Styles und Scripte auch registriert werden können, um sie zu einem späteren Zeitpunkt mit den enqueue-Befehlen zu aktivieren.11 Wenn das Script zuvor nicht registriert war, übernimmt das auch der enqueue-Befehl.
Dazu sind zumindest zwei Paramter zu übergeben. Zum einen das sogenannte Handle, ein eindeutiger Bezeichner des Scripts (mit Hilfe dessen es später auch wieder deaktiviert werden kann), zum anderen den absolute Pfad zum Script.
Unserem Stylesheet weisen wir das Handle 'irm-style'
zu und geben die URL an. Unserem Script weisen wir das Handle 'irm-script'
zu und geben ebenfalls die URL an. Darüber hinaus geben wir allerdings noch drei weitere Parameter an. Der dritte Parameter ist ein Array und enthält Scripte die aktiv sein müssen, damit unser Script funktionieren kann. Dort geben wir 'jquery'
an, das Handle für jQuery, welches nativ von WordPress unterstützt wird. Sollte es aus irgendeinem Grund deaktiviert sein, so weiß WordPress nun, das wir dieses Script benötigen und es aktiviert werden muss. Dahinter geben wir noch eine Versionsnummer an. Und mit dem Boolean true
, welchen wir als letzten übergeben, erklären wir, dass wir dieses Script erst im Footer laden möchten (was sich positiv auf die Ladezeiten der Webseite auswirkt).
Nun können wir also in Ruhe unsere beiden Dateien style.css und script.js anlegen und dort unser Plugin ein wenig stylen und die Javascript-Funktionalität gestalten.
Die style.css:
.read_more_title{
cursor: pointer;
text-decoration: underline;
font-weight: bold;
}
read_more_body{
display: none;
}
plugins/4-read-more-link/style.css
Die script.js:
jQuery
( document
).ready
( function
(){
jQuery
( 'a.read_more_title'
).click
( function
(event
){
event.preventDefault
();
jQuery
( this
).
parent
().
children
( '.read_more_body'
).
slideToggle
();
});
});
plugins/4-read-more-link/script.js
Ich setze an dieser Stelle voraus, dass Sie sich schon ein wenig in CSS und Javascript respektive jQuery auskennen. Nur kurz möchte ich das Script etwas kommentieren. Darin legen wir lediglich fest, dass, sobald auf . read_more_title
geklickt wird, der Text in . read_more_body
entweder angezeigt wird, oder – falls er schon sichtbar ist – wieder unsichtbar gemacht wird.
Sie sehen auch, dass wir jQuery(document)
schreiben und nicht die Kurzschreibwiese $(document)
. Neben den jQuery-Bibliotheken unterstützt WordPress auch andere Frameworks, darunter Prototype12, welches auch im Admin Verwendung findet. Auch Prototype setzt auf die Kurzschreibweise $
, weshalb es hier zu einem Konflikt zwischen den beiden Bibliotheken kommt. WordPress unterstützt deshalb das Dollarzeichen als Kurzschreibweise für jQuery nicht.
Wenn Sie auf die $-Schreibweise nicht verzichten möchten, können Sie wie folgt vorgehen:
(function
($
) {
//Nun koennen Sie statt jQuery $ schreiben!
$
( document
).ready
( function
(){
console.log
( $
);
});
})( jQuery
);
In diesem Script erzeugen wir eine anonyme Funktion, welche als Parameter $
aufnimmt. In der letzten Zeile sehen Sie, dass wir diese anonyme Funktion ausführen und dabei jQuery
übergeben. Dadurch können wir nun innerhalb der Routine jQuery über die Kurzschreibweise $
nutzen. Wenn Sie also beispielsweise jQuery-Bibliotheken verwenden möchten, die komplett auf der Kurzschreibweise basieren, können Sie diese innerhalb einer solchen Funktion ausführen statt den kompletten Quellcode der Bibliothek umzubauen.
10.Wenn Sie statt eines Shortcodes lieber einen Block definieren möchten, sollten Sie sich mit der Erstellung von Blöcken im Allgemeinen (S. 247) und insbesondere mit der Erstellung dynamischer Blöcke (S. 277) beschäftigen.
11.Wenn Sie mehr über die Registrier-Funktionen erfahren wollen, empfehle ich Ihnen die entsprechenden Einträge im WordPress Codex: http://codex.wordpress.org/Function_Reference/wp_register_style, http://codex.wordpress.org/Function_Reference/wp_register_script
12.http://prototypejs.org/
Ein zentrales, bisher noch nicht erörtertes Konzept sind die Widgets in der Sidebar. Sie kennen sicherlich schon die Standard Kategorien-Ansicht, welche bei vielen Blogs in der Sidebar zu sehen ist, oder das Archiv, die Blogroll und so weiter. Als Plugin Entwickler können Sie auch selbst sogenannte Widgets entwickeln, welche dann vom WordPress Administrator in der Sidebar eingepflegt werden können. Auch Widgets werden über einen Action Hook eingebunden: 'widgets_init'
<?php
add_action
( 'widgets_init', 'mein_widget'
);
function mein_widget
(){
register_widget
( 'Mein_Widget'
);
}
plugins/5-widget/index.php
In der Funktion mein_widget()
registrieren wir nun unser neues Widget mit Hilfe von register_widget()
. Dabei übergeben wir dieser Funktion den Namen einer Klasse, welche wir noch definieren werden. Diese enthält dann alle weiteren Definitionen für unser Widget und erweitert die von WordPress gelieferte Klasse WP_Widget
. Betrachten wir zunächst den grundlegenden Aufbau dieser neuen Klasse:
<?php
class Mein_Widget extends WP_Widget
{
function __construct
() {}
function widget
( $args, $instance
) {}
function update
( $new_instance, $old_instance
) {}
function form
( $instance
) {}
}
Im Wesentlichen besteht diese aus vier Methoden:
__construct()
Methodewidget()
update()
form()
Wir gehen nun Schritt für Schritt diese vier Funktionen durch. Die erste Funktion enthält grundlegende Informationen zu dem Widget, wie Titel und Beschreibung.
function __construct
() {
parent::__construct
(
'widget-id',
'Widget Titel',
array(
'description' => 'Beschreibung'
)
);
}
plugins/5-widget/widget.php
Mit dieser Funktion wollen wir uns nicht so lange aufhalten. Sie geben hier einfach die grundlegenden Werte an. Auch einen eindeutigen Bezeichner, eine ID, müssen Sie (siehe Zeile drei) angeben.
Die Funktion widget()
dient der Ausgabe des Widgets und rendert den HTML-Code, welcher schließlich in der Sidebar erscheinen soll. Zwei Argumente werden hier übergeben: $args
und $instance
. Die erste Variable ($args
) enthält Informationen von der Sidebar. Wie beispielsweise ein Widget umschlossen wird (ob als <div>
oder als <li>
) und wie der Widget-Titel umschlossen wird (ob als <h1>
, <h2>
oder <p>
). Diese Informationen werden hinterlegt, wenn eine Sidebar registriert wird.13 Die Variable $instance
enthält Informationen, welche speziell für das Widget hinterlegt wurden. Sie werden später in der Funktion form()
lernen, wie Sie über die $instance
das Erscheinungsbild Ihres Widgets konfigurierbar machen können. Eine simple Widget Ausgabe könnte also wie folgt aussehen:
function widget
( $args, $instance
) {
echo $args
['before_widget'
];
if
( !
empty( $instance
['title'
] ) ) {
echo $args
['before_title'
] .
apply_filters
(
'widget_title',
$instance
['title'
]
).
$args
['after_title'
];
}
echo 'Hallo Welt';
echo $args
['after_widget'
];
}
plugins/5-widget/widget.php
In Zeile zwei geben wir zunächst den HTML-Code aus, welcher vor einem Widget ausgegeben werden soll. Wir prüfen dann, ob über $instance
ein Titel übergeben wurde und wenn ja, geben wir zunächst den HTML-Code aus, welcher vor dem Titel kommen soll ( $args['before_title']
) um anschließend den Titel auszugeben. In Zeile fünf passiert noch etwas interessantes: apply_filters()
. Sie wissen ja schon, wie man mit Hilfe von Hooks Daten filtern kann. Mit apply_filters()
können Sie nun selbst Daten durch Filter durchlaufen lassen. In diesem Fall möchten wir unseren Titel über 'widget_title'
filtern lassen. An dieser Stelle sei erwähnt, dass Sie Action Hooks mit der Funktion do_action()
ausführen. Beide übergeben als ersten Parameter den Bezeichner des Hooks, der auszuführen ist. Danach folgt eine beliebige Anzahl von Argumenten, welche an die eingehakten Prozesse übergeben werden. Bei apply_filters()
dient das erste Argument dabei als Wert, der gefiltert werden soll. So können Sie sich in sämtliche Filter des WordPress-Systems quasi nicht nur an dem einen, sondern auch an dem anderen Ende einklinken. Sie können Daten filtern oder Ihre Daten filtern lassen! Schließlich schließen wir unseren Titel mit $args['after_title']
ab, geben noch einmal ein „Hallo Welt“ aus und schließen das Widget mit $args['after_widget']
ab.
Nun ist es aber wirklich an der Zeit, dass Sie ein Widget auch konfigurierbar machen können! Dazu dienen update()
und form()
. Die Funktion form()
dient der Ausgabe der Konfigurationsform im Admin. update()
übernimmt im Anschluss das Speichern dieser Daten in der Datenbank. Machen wir uns mit dem Prinzip vertraut: Im ersten Schritt werden wir dem Administrator die Möglichkeit geben, unserem Widget einen Titel zu geben, den wir dann im zweiten Schritt speichern und mit dem obigen Code ausgeben können.