• include vs. include_once

    von am 24. Dezember 2008

    Nur schon mal vorweg, alles was ich hier schreibe gilt auch für require und require_once.

    Ich wurde schön des öfteren gefragt, wann man include und wann include_once verwenden sollte. Die Antwort ist meiner Meinung nach ganz einfach. Include nie, include_once immer. Aber wie meistens kann man sich über dieses Thema auch gediegen streiten. Ich, in meiner objektorientierten Denkweise, sehe aber keinen Grund eine Datei mehrmals inkludieren zu wollen.

    Pro Datei existiert genau eine Klasse und kein ausführbarer Code. Die einzige Stelle, in der solcher Code vorhanden ist, sollte die index.php sein. Natürlich gibt es auch ein paar Ausnahmen, die von PHP vorgegeben sind. So würde ich die autoload Methoden zum Beispiel nicht in eine Klasse packen. Aber auch eine Datei, in der diese Methoden vorhanden sind, sollte genau einmal inkludiert werden. In den meisten Fällen kann ein include durch die Verwendung einer Funktion ersetzt werden. Wer includes einsetzt, um duplizierten Code zu verhindern, der sollte auf traits warten, denn diese sind für genau solche Fälle gemacht. Und wenn ich ehrlich bin, dann habe ich lieber doppelten Code, als includes, denn hier versagen wenigstens die Methoden der statischen Codeanalyse nicht. Und auch wenn sie vielleicht nicht versagen, erschwert wird es dadurch erheblich.

    Falls ihr euch nichts unter dem Codeduplizieren vorstellen könnt, hier ein kleines Beispiel:

    <?php
    
      class ASingleton
      {
         // ...
         public static function getInstance( )
         {
           return include 'singleton_getInstance.php';
         }
      }
    
    ?>

    In der singleton_getInstance.php steht nun der Code, der dazu benötigt wird eine Instanz zu erstellen. Eine Klasse BSingleton könnte nun genau den gleichen Code Snippet verwenden. Vielleicht denkt ihr euch jetzt, dass man das ganze auch über Ableitung hinbekommen könnte, aber da gibt es ein Problem. Zieht man hier Vererbung hinzu, so verbauen wir uns die Möglichkeit von anderen Klassen abzuleiten und in den meisten Fällen wollen wir das nicht.

    Nils Langner

    Auch wenn Ihr es mir nicht glauben werdet, aber ich habe nichts gegen PHP. Ich rege mich einfach nur gerne auf. Ok so schlimm ist es auch nicht. Eigentlich wollte ich schon immer einen Blog haben und da ...

    Zum Profil von Nils Langner

    10 Kommentare »


    • Sven
      am 24. Dezember 2008 um 09:29 Uhr

      Hallo,

      ich verwende immer require_once() obwohl ich mal irgendwo gelesen hab das es angeblich ein Performance-Killer sein soll.
      Hat jemand dazu nähere Informationen?


    • kb
      am 24. Dezember 2008 um 09:40 Uhr

      require_once ist kein Performancekiller. Bei require wird das Script halt angehalten wenn die Datei nicht da ist, bei include wird nur eine Fehlermeldung geworfen und das Script weiter ausgeführt :)

      Der Phpperformanceblog hat das schon mal verglichen, ausführtechnisch liegen die gleichauf. Glaub ich mich zu erinnern.


    • Axel
      am 24. Dezember 2008 um 10:03 Uhr

      Ich verwende eigentlich nur include statments. Dazu packe ich einfache define Anweisungen um die entsprechende Klasse.

      Beispiel:

      class.php

      index.php

      gruss axel


    • Axel
      am 24. Dezember 2008 um 10:04 Uhr

      hmmm irgendwie wird mein code wegoptimiert :D

      zweiter versuch:

      Beispiel:

      class.php

      index.php

      include( ‘class.php’ );
      include( ‘class.php’ );
      include( ‘class.php’ );
      include( ‘class.php’ );

      gruss axel


    • Axel
      am 24. Dezember 2008 um 10:05 Uhr

      versuch 3:

      class.php

      if( defined( __FILE__ ) )
      {
      return;
      }

      define( __FILE__, 1 );

      class Asa
      {
      public function cool()
      {
      die(‘happy x-mas’);
      }
      }

      index.php

      include( ‘class.php’ );
      include( ‘class.php’ );
      include( ‘class.php’ );
      include( ‘class.php’ );


    • admin
      am 24. Dezember 2008 um 11:19 Uhr

      @Axel, da sieht man, dass du aus der C++ Ecke kommst.


    • Stephan Hochdoerfer
      am 24. Dezember 2008 um 11:26 Uhr

      Ich denke es gibt einige Strategien um das Includen von Dateien zu beschleunigen. Abhängig vom Projekt bzw. dessen Laufzeitumgebung lässt sich in die eine oder andere Richtung hinoptimieren. Ich verwende i.d.R. eine Kombination von autoload und include, sprich in einer mittels autoload registrierten Funktion wird der include durchgeführt. Persönlich habe ich den Eindruck dass dies deutlich performanter ist als include_once oder require_once. In neueren PHP Versionen sollen die beiden _once Funktionen zwar einen “realpath cache” zur Performance-Steigerung bekommen haben, das konnte ich aber lokal in verschiedenen Tests nicht direkt nachvollziehen. Ein weiterer wichtiger Punkt ist wie ich finde die Verwendung von absoluten Includepfaden (bzw. realativ zu einem absoluten Verzeichnis). Dies steigert die Performance ebenfalls da nur ein File-Request auf OS Basis abgesetzt wird (direct hit), im Gegensatz zu x Leseanfragen, für (fast) alle Verzeichnisse die als include_path gesetzt wurden. Alternativ dazu sind Opcode Caches auch ein Ansatz um viele Dateizugriffe zu verhindern.


    • unset
      am 24. Dezember 2008 um 12:11 Uhr

      Duplicate Code ist ein Anti-Pattern und sollte nie vorkommen. Das wie von dir oben beschrieben zu verhindern ist eher Banane. Ich sehe keinen Vorteil darin, den Methodenkörper auszulagern. Mehr als eine Klasse erweitern kann und soll PHP nicht. Dafür gibt es interfaces. Das ist ohnehin auch nicht nötig, wenn man eine sinnvolle Klassenvererbung wählt.

      Aber vielleicht verstehe ich dich auch falsch.


    • admin
      am 24. Dezember 2008 um 13:51 Uhr

      @unset: naja versuche mal ein Singleton schön über Vererbung zu implementieren, ohne dir dabei was für die Zukunft zu verbauen. In den meisten Fällen wirst du dann doch duplizierten Code haben.


    • infogurke
      am 26. Dezember 2008 um 09:07 Uhr

      *_once ist teuer! Genau aus dem Grund gibt es in APC die Option die beiden Funktion durch eine optimierte Version überschreiben zu lassen.

      Wichtig ist auch, dass *immer* absolute Pfade verwendet werden und das der include_path möglichst klein ist.

      Setzt einfach mal in APC die Option apc.stat=0. Daraufhin überprüft APC nicht mehr bei jedem Requests ob sich die PHP-Datei verändert hat. Zusätzlich, und das ist das schöne, gibt APC dann eine Fehlermeldung aus, wenn die Datei nicht gecached werden kann, z.B. wegen relativen Pfaden.

    RSS Feed für Kommentare zu diesem Artikel. TrackBack URL

    Hinterlasse einen Kommentar

    Werbung
    PHP Magazin
    Ausgabe 02/2010

    Dieses Mal mit Artikeln zu den Themen OpenSocial und Apache Shindig, Graphentheorie, Smarty3

    t3n
    Ausgabe 19

    Social Media (R)evolution. Weitere Themen sind noSQL, Crowdsourcing ...

    PHP Journal
    Ausgabe 2/2010

    PHP & Windows optimal nutzen, die besten PHP-CMS im Überblick, Google-API mit Zend Framework nutzen.

    Wir wurden schon öfters gefragt, ob man uns nicht irgendwie unterstützen kann. Die Antwort war immer einfach: Klar! Am einfachsten ist es eure nächsten Einkäufe bei Amazon über unsere Link abzuwickeln. Damit würdet ihr uns schon sehr helfen. Über Co-Autoren freuen wir uns aber noch mehr.