mermshaus: Wie HTML Schnipsel zusammensetzen und ausgeben?

Beitrag lesen

Das ist jetzt eine völlig andere Frage als in deinem Ausgangsbeitrag. 😉 Aus Performance-Sicht kann das grundsätzlich auf jede von dir genannten Weise umgesetzt werden. Es gibt keine prinzipiellen Bedenken, die gegen irgendwas davon sprechen.

Output-Buffering ist in diesem Kontext eine Hilfsmechanik, um beispielsweise in PHP-Templates den „HTML-Modus“ nutzen zu können (Direktausgaben außerhalb von <?php…?>-Tags) und um dennoch die Template-Rückgabe erst mal als String weiterverarbeiten zu können. Das ist grundsätzlich durchaus sinnvoll, weil dadurch möglicherweise vermieden wird, alle HTML-Ausgaben umständlich als PHP-Strings zusammenbauen zu müssen, was unleserlich ist. Zudem kann mit Output-Buffering vermieden werden, halbfertige Seiten auszuliefern, wenn in den Templates Fehler auftreten. In diesem Fall kann der bisher generierte Ausgabe-Buffer verworfen und eine neue Fehlerseite erzeugt werden. Ein Nachteil in manchen Fällen ist, dass der gesamte Inhalt oder große Teile des Inhalts gleichzeitig im Speicher gehalten werden. Das ergibt bei Downloads zum Beispiel wenig Sinn. Bei normalen HTML-Seiten ist es recht egal, solange keine besonderen Anforderungen vorliegen.

Includes binden weitere PHP-Dateien ein und führen den Inhalt dabei als Code aus. Das ist im Templating hilfreich, wenn PHP als Templatesprache genutzt wird, da damit in Template-Dateien auf Variablen und die üblichen Kontrollstrukturen (Bedingungen, Schleifen, …) zurückgegriffen werden kann, was im Grunde essenzielle Funktionalität ist. Die Alternative dazu sind Template-Engines mit eigener Syntax, die diese Konstrukte anbietet. (Die kompilieren aber in der Regel aus Geschwindigkeitsgründen den eigenen Code auch nach PHP.)

file_get_contents bietet in dem Sinne nur sehr eingeschränktes Templating, weil von sich aus in der eingebundenen Datei kein Logikcode (Variablen, Schleifen, …) ausgeführt wird. Für das Einbinden rein statischer Inhalte ist die Funktion grundsätzlich nutzbar, aber wenn ansonsten sowieso „echtes“ Templating mit Logikcode in Templates genutzt wird, kann auch ein statischer HTML-Inhalt problemlos auf die „echte“ Weise eingebunden werden. file_get_contents ist dann eher für Inhalte, in denen by design kein PHP-Code direkt ausgeführt werden darf, weil es sich vielleicht um User-Uploads handelt oder dergleichen.

* * *

Den Ansatz, in jeder Template-Seite explizit Header und Footer zu inkludieren, halte ich für nicht so praktisch. Ich würde auf eine geschachtelte Struktur setzen, in der der eigentliche Seiteninhalt erzeugt wird, der dann in ein HTML-Rahmenlayout eingefügt wird. Das ist mit PHP recht simpel zu bauen, aber ähnliche Konzepte gibt es in Template-Engines wie Twig auch bereits integriert:

Für kleine Sachen nutze ich oft Code, der grob so aussieht:

(Anmerkung: In den Beispielen fehlt aus Gründen der Lesbarkeit gegebenenfalls Escaping bei Kontextwechseln (htmlspecialchars).)

function render($__templateFile, array $tpl = array())
{
    require __DIR__ . '/view/' . $__templateFile . '.phtml';
}

Das rufe ich dann zum Beispiel so auf:

// Template-Werte für Index-Seite
$vars = array(
    'posts' => getNewestPosts()
);

render('layout', array(
    'title'   => 'Homepage',
    'content' => render('index', $vars)
));

layout.phtml:

<!doctype html>
<html lang="de">

<meta>
    ...
    <title><?=$tpl['title']?></title>
    ...
</meta>

<body>
    ...
    <?=$tpl['content']?>
    ...
</body>

</html>

index.phtml:

<h1>Startseite</h1>

<?php foreach ($tpl['posts'] as $post): ?>
    <?php render('_post', array('post' => $post)); ?>
<?php endforeach; ?>

Das kommt in diesem Fall ohne Output-Buffering aus und lässt sich natürlich beliebig eleganter gestalten. Zum Beispiel mit eigenen View-Klassen. Das würde ich mir bei Interesse ruhig mal in einem der verbreiteten Frameworks (Laravel, Symfony, Zend, Yii, …) anschauen.