Rolf B: Spricht etwas gegen die exzessive Verwendung von php include?

Beitrag lesen

Hallo borisbaer,

du musst bedenken, dass jeder include mehrere Dinge auslöst:

  • Zugriff auf das Dateisystem
  • Compilieren des enthaltenen PHP Codes im Kontext der Stelle, wo der include steht.

„Compilieren“ ist je nach PHP Version eine großzügige Bezeichnung, aber auf jeden Fall wird der Quelltext in einen Bytecode umgewandelt, der dann zur Ausführungszeit von der ZEND-Engine interpretiert wird. Neuere PHP Versionen besitzen einen Just-in-Time Compiler, der den Bytecode vor Ausführung in tatsächliche Maschinenbefehle umsetzt.

In wie weit der erzeugte Code tatsächlich kontextabhängig ist, weiß ich nicht. Ich meine damit den Zugriff auf Variablen und Funktionen - man kann einen Namen bei jedem Zugriff durch das Durchsuchen der entsprechenden Verzeichnisse auflösen, oder man tut das einmal bei der Codeumwandlung und speichert die Referenz - aber letzteres setzt eben voraus, dass sich die Umgebung dann nicht mehr ändert. In einer dynamischen Welt wie PHP kann das knifflig sein.

Es kann also sein, dass eine include-Flut kontraproduktiv für die Ausführungsgeschwindigkeit und auch für die Ladezeit des Scripts ist.

Dem entgegen stehen die Caching-Mechanismen von PHP, vor allem der ZEND Opcache. Wenn Du foo.php lädst, wird daraus Bytecode generiert und vom Opcache gespeichert. Wann immer Du foo.php dann nochmal aufrufst, wird geprüft, ob der Bytecode noch im Cache ist und ob der Timestamp von foo.php unverändert ist. Wenn foo.php nun zweiunddrölfzig Includes einbindet, bekommt jedes Include einen eigenen Opcache-Eintrag, und natürlich muss PHP dann für jeden Eintrag vor Verwendung prüfen, ob der Sourcecode nicht erneuert wurde.

Auf einem schwach belasteten Server wird das alles in memory in Caches ablaufen; auf einem schwachbrüstigen Server mit ordentlicher Last kann das dagegen richtig schmerzhaft sein.

Es ist vermutlich hilfreich, die Teile, die Du in includes auslagern willst, zumindest in Gruppen zu ordnen. Jeden Teil, den Du wiederverwenden willst, packst Du in eine Funktion. Und an der Stelle, wo Du den Teil brauchst, rufst Du die Funktion auf.

Mal als ganz dummes Beispiel - das in dieser Form natürlich frei von Nutzen ist:

<?php
// tables.inc

function beginTable() {
?>
   <table>
<?php
}

function endTable() {
?>
   </table>
<?php
}

function beginRow() {
?>
   <tr>
<?php
}

function endRow() {
?>
   </tr>
<?php
}

function headCell($content) {
?>
   <th><?= htmlspecialchars($content) ?></th>
<?php

function dataCell($content) {
?>
   <td><?= htmlspecialchars($content) ?></td>
<?php
}

<?php
include "tables.inc"

beginTable();
for ($i=0; $i<10; $i++) 
{
   beginRow();
   headCell("Zeile $i");
   dataCell("foo");
   dataCell("bar");
   dataCell("baz");
   endRow();   
}
endTable();

Wie gesagt: in dieser Form sicherlich nicht sehr sinnvoll, es geht nur um's Prinzip.

An Stelle von 5 Includes ist es nur eines, und die Bausteine werden als Funktionen aufgerufen. Selbst wenn ein PHP Script nur die Hälfte der Funktionen in einem solchen Include braucht, ist das auf Grund des Opcache immer noch die bessere Lösung als viele kleinste Dateien.

Solche Funktionen kann man auch als Klassen organisieren, man kann die Struktur des erzeugten HTML auch über Funktionsparameter abbilden, da gibt's 1000 Möglichkeiten, die Dinge zu verkomplizieren (oder eleganter zu machen, je nach Sichtweise).

Meine Meinung, jedenfalls.

Rolf

--
sumpsi - posui - obstruxi