PHP/Tutorials/Templates/Verarbeitung
Bei der Verarbeitung von Daten innerhalb der Geschäftslogik kommt es zwangsläufig dazu, dass ein Ergebnis ausgegeben werden muss. Das bedeutet, dass im HTML-Dokument, das an den Browser gehen wird, dieses Ergebnis an irgendeiner Stelle mit passendem HTML-Code versehen eingetragen werden muss. Aber wie und wo? Und wann soll das wo in welchem Teil des PHP-Programms entschieden werden?
Die Idee mit den festen Seitenbestandteilen
Kehren wir zurück zu unserem ersten Beispiel aus der Einführung, in dem wir feste Bestandteile der Seite mittels include
-Anweisungen eingefügt haben. Das Beispiel war unnötig stark aufgeteilt worden, um zu zeigen, welche Problematiken sich beim Zusammensetzen ergeben. Wie wäre es denn, wenn wir
- mit einem vollständigen und korrekten HTML-Dokument anfingen, in dem die festen Seitenbestandteile schon alle eingetragen stehen und
- dann nur die angeforderten Inhalte dynamisch eingefügt werden müssen?
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Unsere Firma</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<a href="/">Unsere Firma - Kompetenz in allen Fingern</a>
</header>
<main>
<h1>Willkommen auf unserer Website!</h1>
<p>Das Motto unserer Firma ist "Kompetenz in allen Fingern",
denn bei uns arbeitet mehr als nur eine Hand.</p>
</main>
<nav>
<h2>Unterseiten</h2>
<ul>
<li><a href="products.html">Produkte</a></li>
<li><a href="team.html">Wer wir sind</a></li>
<li><a href="contact.html">Kontakt/Impressum</a></li>
</ul>
</nav>
<footer>(C) 2010 Unsere Firma</footer>
</body>
</html>
Für ein so simples Konzept wie eine online-Visitenkarte mit wenigen Unterseiten ist dieses Template schon fast die fertige Seite. Wenn also die Homepage (im Sinne von "Einstiegsseite") aufgerufen wird, kann das Template unverändert an den Browser gegeben werden. Soll allerdings eine Unterseite ausgegeben werden, so müsste nur der Inhalt des <main>
-Elements ausgetauscht werden.
Unterseiten mit „ohne“
Die Inhalte der jeweiligen Unterseite könnten dann in einem ganz kahlen aber vollständigen HTML-Dokument stehen:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Wer wir sind</title>
</head>
<body>
<h1>Wer wir sind</h1>
<p>Wir sind ein mittelständisches Unternehmen,
das sich zufriedene Kunden auf seine Fahnen
geschrieben hat.</p>
</body>
</html>
Aus dem HTML-Dokument der Unterseite benötigen wir den Inhalt des title
- und des body
-Elements, um ihn in unserem Template-Dokument einzufügen. Im Falle des Seitentitels bietet es sich an, den vorherigen Inhalt dort stehen zu lassen und den Titel der Unterseite davor einzufügen. Was den Inhalt des body
-Elements betrifft, so ersetzt er alles, was im Template-Dokument im main
-Element stand:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Wer wir sind - Unsere Firma</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<a href="/">Unsere Firma - Kompetenz in allen Fingern</a>
</header>
<main>
<h1>Wer wir sind</h1>
<p>Wir sind ein mittelständisches Unternehmen,
das sich zufriedene Kunden auf seine Fahnen
geschrieben hat.</p>
</main>
<nav>
<h2>Unterseiten</h2>
<ul>
<li><a href="index.php/products">Produkte</a></li>
<li><a href="index.php/team">Wer wir sind</a></li>
<li><a href="index.php/contact">Kontakt/Impressum</a></li>
</ul>
</nav>
<footer>(C) 2010 Unsere Firma</footer>
</body>
</html>
Man erkennt es an der nicht ganz passenden Einrückung, dass hier der body
-Inhalt ersatzweise eingefügt wurde. Auch am Seitentitel erkennt man die Veränderung im Vergleich.
Zusammenführen von Inhalt und Vorlagen
Bei der Verwendung der DOM-Klassen ist eine solche Ersetzung schnell gemacht.
<?php
// home.html as default
$tmp = DOMDocument -> loadHTMLFile('home.html');
// nur Demo - wir sparen uns hier den Mechanismus
// zur echten Erkennung der gewünschten Seite
$requested = 'team';
if (is_file("$requested.html")) {
$page = DOMDocument -> loadHTMLFile("$requested.html");
// get <title> contents
$title = '';
foreach ($page -> getElementsByTagName('title') as $node) {
$title = $node -> textContent;
}
// into template
foreach ($tmp -> getElementsByTagName('title') as $node) {
$node -> insertBefore(
$tmp -> createTextNode("$title - "),
$node -> firstChild
);
}
// insert <body> contents into template's <main>
foreach ($tmp -> getElementsByTagName('main') as $main) {
// empty <main>
while ($main -> firstChild) {
$main -> removeChild($main -> firstChild);
}
// copy contents into template
foreach ($page -> getElementsByTagName('body') as $body) {
while ($body -> firstChild) {
$main -> appendChild(
$tmp -> importNode($body -> firstChild, true)
);
// remove copied node from original
$body -> removeChild($body -> firstChild);
}
}
}
}
echo $template -> saveHTML();
Diese Art Template ist die einfachste. Man nimmt im Grunde fertige Bausteine und fügt sie passend aneinander. Damit die formale Korrektheit des HTML-Codes gegeben ist, greift man auf eine Klasse zurück, die diese Korrektheit garantiert.
ToDo (weitere ToDos)
Dieses Tutorial beschreibt die Grundlagen.
Interessant wäre es, jetzt alle HTML-Dokumente eines Ordners zu erfassen und neben header und footer auch eine Navigation zu erstellen. Diese würde aus den Dateinamen (URL) und den Inhalten der title-Elemente vom Script automatisch erstellt werden.
Dabei könnte auf das Beispiel im 2. Kapitel (PHP/Tutorials/Templates/Dateien_mit_include_nachladen#Auslagern_der_Navigation) zurückgegriffen werden.
--Matthias Scharwies (Diskussion) 14:59, 21. Okt. 2022 (CEST)
DOMDocument
-Objekt eingelesen. In der letzten Zeile wird dasDOMDocument
-Objekt zu HTML-Code serialisiert und an den Browser ausgegeben. Für die Startseite mag das als völlig unnötig erscheinen, aber sollte im HTML-Code ein formaler Fehler sein, so wird der Browser durch dieDOMDocument
-Klasse garantiert mit korrektem HTML beliefert.Die Methode
Das Umkopieren aus der Unterseite ins Template benötigt zwei eigenständige Instanzen dergetElementsByTagName
liefert eine Array-artige Liste an gefundenen Elementknoten zurück, in der jeweils nur ein Element vorhanden sein sollte. Der Einfachheit halber wurde der Zugriff auf dieses innerhalb einerforeach
-Schleife notiert, obwohl es höchstens eines gibt. Falls der Elementknoten aber nicht gefunden werden sollte, so wird die Schleife überhaupt nicht ausgeführt. Ohne Schleife hätten wir mühsam die Existenz des Elementknotens prüfen müssen und eineif
-Verzweigung gebraucht.DOMDocument
-Klasse, für jede HTML-Datei eine eigene. Damit das Template-Dokument einen DOM-Knoten aus dem anderen Dokument verarbeiten kann, muss dieser mittelsimportNode
zuerst ins eigene Dokument importiert werden. Der zweite Parameter (hier mit dem Werttrue
) entscheidet, ob Kindknoten ebenfalls importiert werden sollen.