Ursprünglich war PHP eine Template-Sprache die HTML etwas Dynamik verleihen sollte. Das PHP über dieses Stadium schon sehr (sehr, sehr) lange hinausgewachsen ist, dürfte bekannt sein. Dennoch wird PHP häufig noch genauso verwendet wie in seinen Anfangstagen. Zu meinem persönlichen Leidwesen unterstützt PHP dies aus Gründen der Rückwärtskompatibilität auch weiterhin. Bei der Arbeit an so manchem Script sollte sich keine funktionsbereite Kettensäge in Reichweite befinden, da ansonsten Gefahr besteht das am Autor des Scriptes ein Funktionstest der Kettensäge vorgenommen wird.
Vor allem bei WordPress sieht man folgende Konstrukte sehr häufig. Das hängt zum einen damit zusammen das WordPress keine Template-Engine hat und man gewissermaßen dazu gezwungen wird PHP und HTML zu vermischen. Zum anderen hängt es wohl auch damit zusammen, dass irgend ein Sepp bei WordPress mal damit angefangen hat solch grausige Konstrukte zu erstellen und jetzt einfach nicht mehr damit aufhören kann.
<?php $href = 'http://example.com'; $title = 'Link zu Example.com'; $class = 'example_link'; $id = 'first_anchor'; $text = 'Dies ist ein Link zu Example.com'; ?> <a href="<?php echo $href; ?>" title="<?php echo $title; ?>" id="<?php echo $id; ?>" class="<?php echo $class; ?>"><?php echo $text; ?></a>
Übersichtlich und lesbar ist was anderes. Wirklich schlimm wird es dann, wenn anstatt der Variablen auch noch Funktionsaufrufe direkt in die Ausgabe gemischt werden. Fehler sind so quasi vorprogrammiert und diese dann zu finden, ist eine Qual.
Deutlich übersichtlicher wird es, wenn man Curly Braces verwendet. Anstatt jede Variable mit einem<?php echo ...; ?>
auszugeben, verwendet man geschweifte Klammern ( { und } ) um die Variable in einem String unterzubringen.
<?php echo "<a href=\"{$href}\" title='{$title}' id='{$id}' class='{$class}'>{$text}</a>"; ?>
Das sieht doch schon mal deutlich übersichtlicher aus, hat aber auch seine Nachteile. Der String muss z.B. in doppelten Anführungszeichen (“) eingeschlossen sein, was zur Folge hat das man innerhalb des Strings nur einfache Anführungszeichen(‘) verwenden kann oder doppelte Anführungszeichen mit einem Backslash maskieren muss (\”).
Zudem funktionieren Funktionsaufrufe nicht mehr so einfach. Man müsste das Ergebnis des Funktionsaufrufes erst in einer Variablen zwischenspeichern bevor man den Wert im String verwenden kann. Dies kann etwas kniffelig werden wenn die Funktion keinen Wert zurück gibt, sondern ihn stattdessen direkt ausgibt.
Arbeitet man mit Klassen, ist es etwas leichter den Rückgabewert einer Funktion im String mit geschweiften Klammern zu integrieren.
<?php class Link { public $href = 'http://example.com'; public $class = 'example_link'; public $id = 'first_anchor'; public $text = 'Dies ist ein Link zu Example.com'; public function get_title(){ return 'Link zu Example.com'; } } $obj = new Link(); echo "<a href='{$obj->href}' title='{$obj->get_title()}' id='{$obj->id}' class='{$obj->class}'>{$obj->text}</a>"; ?>
Genau genommen handelt es sich hierbei um einen Methodenaufruf und nicht um einen Funktionsaufruf. Der “Trick” an der ganzen Sache ist einfach der, dass PHP $obj
wie eine Variable behandelt (was es ja auch ist) und deswegen der Methodenaufruf relativ problemlos möglich ist.
Der größte Nachteil an allen Varianten ist meiner Meinung nach aber der, dass man Logik und Ausgabe miteinander vermischt. Gerade wenn man komplexe Ausgaben hat, wird es schwer die Stelle wiederzufinden an der die gesuchte Ausgabe formatiert wird.
Besser wäre es, wenn man alle Strings zentral an einer Stelle sammelt und in der Logik dann nur noch eine Variable zur Ausgabe verwendet.
<?php $format = "<a href='{$href}' title='{$title}' id='{$id}' class='{$class}'>{$text}</a>"; // some other code... echo $format; ?>
Dies wäre ein netter Ansatz, hat jedoch auch so seine Haken. Denn $format
kann erst gebildet werden, nachdem alle anderen Variablen bereits definiert sind.
<?php $format = "<a href='{$href}' title='{$title}' id='{$id}' class='{$class}'>{$text}</a>"; // some other code... $text = 'Ein anderer Linktext'; echo $format; ?>
Würde zum Beispiel nicht funktionieren. Denn zu dem Zeitpunkt an dem $format
erstellt wird ist $text
noch gar nicht oder mit einen anderen Wert definiert.
Wir bräuchten also eine Funktion die quasi einen abstrakten Formatierungs-String entgegen nimmt und an den entsprechenden Stellen die Werte der Variablen einsetzt. Grundsätzlich hat PHP eine solche Funktion: printf()
bzw. sprintf()
.
printf()
nimmt einen Formatierungs-String und eine Reihe an Variablen entgegen. Die Platzhalter im Formatierungs-String erlauben zudem eine gewisse Formatierung der Ausgabe.
<?php $format = "<a href='%s' title='%s' id='%s' class='%s'>%s</a>"; // some other code... printf( $format, $href, $title, $id, $class, $text ); ?>
Das sieht schon ganz brauchbar aus. Der Formatierungs-String kann z.B. ganz am Anfang des Scriptes definiert werden bevor auch nur eine der verwendeten Variablen definiert wurde. Und man kann anstatt einer Variablen auch einen Funktionsaufruf verwenden.
Einige kleine Nachteile hat printf()
jedoch auch. In der gezeigten Variante muss z.B. die Reihenfolge strikt eingehalten werden. printf()
bietet einige Möglichkeiten wie man die Reihenfolge flexibler gestalten kann und Variablen mehrfach verwenden kann. Zur genauen Verwendung der Formatierung schaut man am besten im PHP-Manual nach.
Aber auch printf()
wird bei komplexen Ausgaben recht schnell unübersichtlich. Vertauscht man zwei Variablen im Funktionsaufruf, kommt es zur fehlerhaften Ausgabe. Auch wenn man die mehrfache Verwendung von Variablen nutzt, muss man die Übersicht behalten an welcher Stelle welche Variable steht.
Im Großen und Ganzen eine etwas unbefriedigende Situation die zu unleserlichen Code und versteckten Fehlern führt. Aus diesen Grund habe ich mir eine Klasse geschrieben mit der ich den Code etwas übersichtlicher gestalten kann.
Die Anforderung lag darin, zum einen die Übersichtlichkeit der Variante mit geschweiften Klammern zu erhalten. Zum anderen die Flexibilität, Abstraktion und Formatierungsmöglichkeiten von printf()
zu haben. Heraus gekommen ist die Klasse Formatter.
Formatter nimmt einen Formatierungs-String ähnlich wie printf()
entgegen, jedoch kann man den Platzhaltern Namen geben, was für mehr Übersichtlichkeit sorgt. Als zweiten Parameter nimmt Formatter ein Array mit Schlüssel-Werte-Paaren oder ein Objekt entgegen. Daher spielt die Reihenfolge in der die Werte definiert werden keine Rolle mehr. Zusätzlich lässt sich die Ausgabe wie bei printf()
formatieren.
<?php $format_time = 'Es ist jetzt %stunden[02d]%:%minuten[02d]%:%sekunden[02d]% Uhr %tageszeit%'; // some other code... $time_values = array( 'tageszeit' => 'mitten in der Nacht', 'stunden' => 1, 'minuten' => 23, 'sekunden' => 8, ); // more code... Formatter::printf( $format_time, $time_values ); // Es ist jetzt 01:23:08 Uhr mitten in der Nacht. ?>
So ist es sehr leicht Formatierung, Logik und Ausgabe voneinander zu trennen und das dann auch noch lesbar zu gestalten. Das es durchaus Vorteile hat das alles voneinander zu trennen, zeige ich dann im nächsten Artikel.
4 Kommentare | Schreibe einen Kommentar