Wie man bei der WordPress-Programmierung für Waffengleichheit sorgt

Alexander Trust, den 15. März 2021
Wordpress - Wallpaper
Wordpress – Wallpaper

Der Titel des Beitrags mag ein wenig kryptisch klingen, dahinter steckt aber eine konkrete Idee, die ich anders gerade nicht umschreiben kann. Die wird aber im Verlauf des Artikels klarer. Noch konkreter geht es um ein Beispiel aus der WordPress-Programmierung und damit um PHP. Allerdings sind diese Konzepte universell einsetzbar, sodass man sie auch in anderen Programmiersprachen abbilden kann und natürlich auch außerhalb von WordPress.

Worum geht es?

Stellt Euch vor, Ihr habt eine Idee für eine Funktion oder am Ende des Tages sogar eine Klasse. Nehmen wir an, Ihr wollt eine Funktion programmieren, die Euch egal in welchem Kontext das passende Bild in Form eines Arrays mit Bildinformationen zurückgibt.

Die Funktion gibt Euch diese Bilddaten sowohl auf der Startseite, als auch in den Archiven und aber auch in einzelnen Beiträgen oder Seiten zurück und Ihr könntet Sie außerdem für viele andere Zwecke nutzen, in denen es immer um Bilder geht. Grob also in etwa:

function my_img() {
…
return $img;
}

Normalerweise verzweifelt man irgendwann daran, dass es viel zu viele Ausnahmen gibt. Denn im Umfeld von WordPress gibt es diverse Funktionen, eine für Artikelbilder (the_post_thumbnail()), eine für Avatare, eine ganz andere, falls Bilder in Form von Metadaten an „Custom Post Types“ angehängt wurden (get_post_meta()), und so fort. Und wenn man die Bilder dann nicht im Rahmen des normalen „Loop“ von WordPress abgreift, sondern mit einem persönlichen Query, dann bekommt man es ohnehin mit einem anderen Ergebnis zu tun (wp_get_attachment_img_src()). Mal hat man dann mit Objekten zu tun, mal mit Arrays, mal mit bloßen Zeichenketten, in denen der URL des Bildes enthalten ist, aber nicht viel mehr.

Ist es nicht nervig, dass man dann überall einen anderen Ansatz für die Entwicklung des eigenen WordPress-Themes benötigt?

Für Waffengleichheit sorgen

Wie bekommt man all diese unterschiedlichen Ergebnisse sortiert? Ganz einfach. Indem man für Ordnung sorgt!

Die Absicht hinter einer eigenen Funktion oder sogar einer Klasse ist ja, dass man sie „immer gleich“ nutzen kann. Mithilfe von Parametern kann man dann noch entscheiden, welcher Code ausgegeben werden soll.

Im Laufe der Arbeit müsst Ihr dann einfach mal einen Schritt zurücktreten und schauen, wo überhaupt Gemeinsamkeiten bestehen. Eine WordPressfunktion wie get_the_post_thumbnail() liefert Euch am Ende des Tages einen fertigen HTML-Tag zurück. Für ein Bild, das als Metadaten zu einem Custom Post Type gespeichert wurde, erhaltet Ihr über get_post_meta() die URL zurück, aber keinen fertigen HTML-Tag. Über wp_get_attachment_img_src() gibt es ein Array, das neben der URL auch die Daten für Breite und Höhe enthält.

Wenn Ihr wollt, dass Ihr Eure Funktion immer auf die gleiche Art verwenden könnt, beispielsweise eine ID des Bildes angebt und dann aber ein Array mit URL, Breite und Höhe zurückbekommt, damit Ihr in Eurem Template dann den HTML-Tag selbst erstellen könnt, müsst Ihr einen gemeinsamen Nenner suchen.

Und was ist beispielsweise für den Fall, dass es gar kein Artikelbild gibt? Ja, auch dann müsst Ihr eben ein Array erstellen, das ein Standardbild als URL enthält, und Angaben für dessen Breite und Höhe.

So eine Funktion könnte unvollständigerweise wie folgt ausschauen:

function my_img($id, $standort) {
	switch($standort) {
		case 'Startseite':
			$img = wp_get_attachment_src($id);
			$my_img = [
				'width' => $img[1],
				'height' => $img[2],
				'url' => $img[0]
			];
			break;
		case 'CPT':
			$img = get_post_meta(…);
			$my_img = [
				'width' => 1920,
				'height' => 1080,
				'url' => $img
			];
	}
	// für den Fall, dass noch gar kein Bild-Array erstellt wurde, müssen wir noch eines hinzufügen.

	if(!isset($my_img)) {
		$my_img = [
			'width' = 1920,
			'height' = 1080,
			'url' = 'Adresse zum Standardbild'
		];
	}
	return $my_img;
} 

Der obige Code ist nicht auf Fehler geprüft, da ich gerade nur einen Texteditor zur Hand habe. Aber mir kam eben gerade jetzt die Idee zu diesem Artikel.

Die Funktion liefert Euch also theoretisch „in jedem Fall“ ein Array mit URL, Breite und Höhe zurück. Auf diese Weise könnt Ihr sie dann immer auf die gleiche Weise verwenden.

Nicht dem Chaos nachgeben

Denn es passiert viel zu schnell, dass man sich mit einer Situation zufriedengibt, in der man sagt, ach komm, an dieser Stelle geht es nun mal nicht, weil da hab ich keine ID vom Bild, sondern nur eine vom Kommentar, und brauche aber den Avatar. Ja, genau dann muss man vorab für Waffengleichheit sorgen.

Das kann man entweder „vorher“, also außerhalb der Funktion. Das ist zu begrüßen. Denn eine Funktion sollte tatsächlich nur eine Aufgabe haben und die immer gleich ausführen. Man könnte es theoretisch auch innerhalb der Funktion, aber das würde die Funktion unnötig aufblähen.

Wenn man also eine ID von einem Kommentar hat und aber die ID des zugehörigen Avatar-Bildes benötigt, muss man im Vorfeld erst mit den vorhandenen Daten diese ID rausfinden. Auch dafür könnte man wieder eine eigene Funktion erstellen, wenn es nicht womöglich auch schon eine bei WordPress gibt. Da ist dann im Fall von WordPress die Code Reference eine gute Anlaufstelle.

Ich habe persönlich eine Weile gebraucht, bis ich vor Jahren irgendwann gemerkt habe, dass es mir hilft, wenn ich in meinen Funktionen für Waffengleichheit sorge, statt ständig neuen Code zu schreiben, oder aber dutzende Ausnahmen zu schaffen.

Denn wenn Ihr wisst, dass Ihr die Funktion my_img() verwendet und immer auf die gleiche Weise verwenden könnt, habt Ihr beim Durchsehen des Quellcodes wesentlich mehr Überblick und ärgert Euch nicht, dass WordPress in dem Kontext mal so programmiert werden will und in einer anderen Situation aber anders. Ihr könnt dann ruhigen Gewissens Eure Vorlagen entwerfen und müsst nur einmal auf die Animositäten von WordPress Rücksicht nehmen, aber eben nicht immer wieder aufs Neue.

Ihr schafft dann einmal „Ordnung“ und könnt Euch immer darauf verlassen, dass Ihr ein korrektes Ergebnis erhaltet, mit dem Ihr arbeiten könnt.

Weitere Beispiele

Die thematisierte Bild-Funktion ist nur ein Beispiel von vielen.

Ich reduziere, wenn ich mit WordPress arbeite, mittlerweile meine Abfragen auf ein Minimum. So kann man eine QUERY nur IDs als Ergebnis zurückgeben lassen, statt vollständige Artikel samt aller Metadaten. Ich bekomme dann ein Array mit IDs zurück und kann es überall sinnvoll einsetzen, egal ob auf der Startseite, in Archiven, oder wo immer ich es möchte.

Statt womöglich mehrere Male einen QUERY zum Beispiel im Template für die Startseite zu nutzen, habe ich mir einfach eine eigene my_query()-Funktion geschrieben. Auch die hat den Vorteil, dass ich immer weiß, was ich am Ende bekomme. Ich kann mittels Parameter den QUERY auf Artikel einer anderen Kategorie steuern. Aber ich kann auch Fälle berücksichtigen, in denen ich vielleicht ähnliche Artikel über Metadaten abfragen möchte. All das kann ich vorab einrichten, sodass ich am Ende bei my_guery() immer die IDs von Artikeln erhalte, mit denen ich weiterarbeiten kann.

Was geht rein, was soll raus

„Früher“ ™ hab ich eigentlich nie darüber nachgedacht, was ich mit Funktionen erreichen möchte. Also grob schon, aber nie im Detail.

Vor Jahren war der Anspruch eigentlich, ein wenig Arbeit zu erleichtern. Das ist er heute zwar immer noch. Doch wenn man sich darauf besinnt, zu prüfen, welche Daten in eine Funktion hineingehen und welche am Ende herauskommen, kann man sogar noch weitere Optimierungen vornehmen.

Zu viele Parameter sind ein „Zeichen“!

Wenn ich beispielsweise merke, dass ich noch einen, und noch einen Parameter brauche und am Ende eine Funktion habe, die zwar alles tut, was sie soll, aber ich womöglich 10, 12 unterschiedliche Parameter brauchen könnte, dann ist das auch nicht im Sinne des Erfinders. Dann ist es eher Zeit, sich vor Augen zu führen, dass ich mit weiteren Funktionen besser bedient bin, um am Ende wieder den Normalzustand herzustellen.

Will heißen: Wenn ich sage, in eine Funktion gehen IDs von Bildern rein und kommen Arrays mit Bildinformationen raus, dann sollte ich diese Funktion nicht damit belasten, aus möglicherweise Artikel-IDs noch Bild-IDs zu extrahieren. Für derartige Fälle kann ich mir lieber einfallen lassen, eine get_my_img_ID()-Funktion zu schreiben, die mir die benötigte Bild-ID liefert, mit der ich meine my_img()-Funktion füttern kann.

Eine Zeichenkette ist eine Zeichenkette, ist eine Zeichenkette?

An dieser Stelle möchte ich zum Ausklang noch ein etwas anderes Beispiel aufführen. Vielleicht kennen manche von Euch die WordPress-Funktion wp_remote_get(), wenn nicht, dann könnt Ihr dessen Funktionsweise in der Code Reference von WordPress nachlesen.

Die Funktion liefert ein Array zurück, das neben den Verbindungsdaten aus dem „Header“ auch den „Body“, also die eigentliche Webseite als Zeichenkette zurückgibt. Wenn Ihr aber am Ende des Tages etwas Anderes benötigt, oder nur Teile davon, dann könnt Ihr natürlich auch hier für Waffengleichheit sorgen, indem Ihr mit einer Funktion das Ergebnis bearbeitet, bis es Euren Bedürfnissen entspricht. Ich habe diese Funktion auch mal verwendet, um URLs von Bildern zu erhalten. Natürlich musste ich dann den Quellcode entsprechend „parsen“.

Einen hab ich noch …

Daran anschließen möchte ich noch einen Hinweis, der prima zum Stichwort Parsen passt. Es gibt ein mächtiges Werkzeug zum Parsen von Dokumenten, das sind die regulären Ausdrücke. Damit kann man tolle Sachen machen, allerdings benötigen reguläre Ausdrücke (REGEX) auch eine gewisse Einarbeitungszeit.

Doch wenn Ihr spontan tatsächlich gewisse „Elemente“ einer HTML-Seite extrahieren oder bearbeiten möchtet, sagen wir alle Bilder, oder alle Links, dann eignet sich dafür auch die PHP-Klasse DOMDocument relativ gut. Wer schon mal mit Javascript programmiert hat, der wird diese Klasse zu schätzen wissen. Denn sie bietet ähnliche Angriffspunkte wie das auch in Javascript genutzte „Document Object Model“ (DOM) und ist aus diesem Grund leichter zugänglich als reguläre Ausdrücke.

Ihr sucht nach einem Anwendungszweck? Ihr könntet mit Javascript, unter manchen Umständen auch mit CSS, gewisse Links kennzeichnen. Aber wenn der Nutzer Javascript ausschaltet, dann ist auch die Kennzeichnung futsch und mit CSS seid Ihr nicht so flexibel. Also könntet Ihr dann den $content von WordPress mit DOMDocument bearbeiten. Damit Ihr am Ende aber nicht weiteren HTML-Tags oder unnötigen Ballast erhaltet, gibt es mittlerweile in PHP passende Parameter, um das zu unterbinden. Für die Funktion „loadHTML“ gibt es nämlich mittlerweile die Parameter LIBXML_HTML_NOIMPLIED und LIBXML_HTML_NODEFDTD. Mehr dazu findet Ihr in der PHP-Dokumentation.

function manipulate_my_content() {
	global $post
	$content = $post->post_content;
	$document = new DOMDocument();
	$document->loadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
	// links extrahieren oder dergleichen geht dann ganz einfach mit:
	$links = $document->getElementsByTagName('a');
	// irgendwas mit den Links anfangen
	…
	// den manipulierten Inhalt speichern und wieder zurückgeben
	return $document->saveHTML();
}

Diese Ansätze, die ich in dem Beitrag erwähnt habe, helfen mir dabei, Waffengleichheit zu erzielen, und mich bei der Arbeit mit WordPress ein wenig voranzubringen.

Vielleicht helfen Sie Euch ja ebenso. Interessant findet Ihr dann womöglich auch die Beiträge:


Ähnliche Nachrichten