Tom: Include_once, require_once

Hello,

kann man innerhalb eines PHP-Includes feststellen, ob das Include mittels include() oder mittels include_once() vorgenommen wurde?

Das darf also nicht in der includierenden Datei stattfinden, sondern in dem Teil, der includiert wird.

Liebe Grüße aus Syburg bei Dortmund

Tom vom Berg

--
Nur selber lernen macht schlau
http://bergpost.annerschbarrich.de
  1. Hi,

    kann man innerhalb eines PHP-Includes feststellen, ob das Include mittels include() oder mittels include_once() vorgenommen wurde?

    Nicht, dass ich wuesste.

    Wozu soll das dienlich sein?

    MfG ChrisB

    --
    „This is the author's opinion, not necessarily that of Starbucks.“
    1. Hello,

      Wozu soll das dienlich sein?

      Ich möchte gewisse Sicherheiten herstellen. Wird ein Modul per include() und NICHT über include_once() eingebunden vom Verwender, dann soll es das Script geordnet beenden und nicht einfach mit einem redeclare-Error "abstürzen" :-)

      Das ist zwar auch über die Abfrage und Erzeugung eines eigenen Subarrays im Projektarray möglich, aber  die andere Möglichkeit hätte ich gerne zusätzlich.

      Liebe Grüße aus Syburg bei Dortmund

      Tom vom Berg

      --
      Nur selber lernen macht schlau
      http://bergpost.annerschbarrich.de
      1. Hi!

        Wozu soll das dienlich sein?

        Ich möchte gewisse Sicherheiten herstellen. Wird ein Modul per include() und NICHT über include_once() eingebunden vom Verwender, dann soll es das Script geordnet beenden und nicht einfach mit einem redeclare-Error "abstürzen" :-)

        Meines Wissens nach, geht das nicht.

        Das ist zwar auch über die Abfrage und Erzeugung eines eigenen Subarrays im Projektarray möglich, aber  die andere Möglichkeit hätte ich gerne zusätzlich.

        Wäre es nicht ggf. sinnvoller, für das Projekt verbindliche Coding Standards zu erstellen, die dem Entwickler vorschreiben, er habe include_once resp. require_once zu verwenden?

        Oder habe ich Deinen Punkt (noch) nicht verstanden?

        off:PP

        --
        "You know that place between sleep and awake, the place where you can still remember dreaming?" (Tinkerbell)
        1. Hello,

          Wäre es nicht ggf. sinnvoller, für das Projekt verbindliche Coding Standards zu erstellen, die dem Entwickler vorschreiben, er habe include_once resp. require_once zu verwenden?

          Oder habe ich Deinen Punkt (noch) nicht verstanden?

          Du hast mich richtig verstanden, aber alles, was man sinnvoll automatisch abfangen kann, muss man nicht mehr vorschreiben. Das übernimmt dann das Modul eigenständig.

          Wer liest schon Readme-Dateien? :-)

          Liebe Grüße aus Syburg bei Dortmund

          Tom vom Berg

          --
          Nur selber lernen macht schlau
          http://bergpost.annerschbarrich.de
          1. Hi!

            Wäre es nicht ggf. sinnvoller, für das Projekt verbindliche Coding Standards zu erstellen, die dem Entwickler vorschreiben, er habe include_once resp. require_once zu verwenden?

            Oder habe ich Deinen Punkt (noch) nicht verstanden?

            Du hast mich richtig verstanden, aber alles, was man sinnvoll automatisch abfangen kann, muss man nicht mehr vorschreiben. Das übernimmt dann das Modul eigenständig.

            Wer liest schon Readme-Dateien? :-)

            Wieso readme? Ist das ein OSS-Projekt?

            Bei Projekten, in denen ich arbeite und gearbeitet habe, gab es zumeist verbindliche Richtlinien, welche alle Entwickler unterschreiben mußten - das klingt hart, aber so etwas funktioniert dann auch.

            off:PP

            --
            "You know that place between sleep and awake, the place where you can still remember dreaming?" (Tinkerbell)
            1. Hello,

              Wer liest schon Readme-Dateien? :-)

              Wieso readme? Ist das ein OSS-Projekt?

              Ich schreibe ein paar Module neu, die man wie einen Baukasten einfach zusammenstöpseln kann und dann hat man die Funktionalität, ohne verstehen zu müssen, wie es eigentlich funktioniert.

              Ich habe mich da mal an Groupwise von Novell orientiert.

              • login
                -- user_management
                -- module_management
              • upload
              • list
              • download
              • message
              • distribute   (Filezugriff für User erlauben, Files verteilen)
              • mail
              • gallery
              • imageedit
                usw...

              Die funktionieren einfach durch Einbindung. Die "Namensräume" trennen sich automatisch über den Dateinamen des jeweiligen Moduls. Wenn man es umbenennt, ändert sich auch der Name des Teilbaums im Array. Es stehen Output-Werte fürs HTML-Template automatisch zur Verfügung ... usw.

              Das hat immer schon ganz gut funktioniert, die Leute mussten aber immer noch viel lesen (so ca. zwei Seiten *g*), ums anwenden zu können. Das hat keiner wirklich gemacht und dann bekomme ich immer emails "wie geht das?". Das ist mir langsam zu blöd.

              Liebe Grüße aus Syburg bei Dortmund

              Tom vom Berg

              --
              Nur selber lernen macht schlau
              http://bergpost.annerschbarrich.de
              1. Hi Tom!

                Wer liest schon Readme-Dateien? :-)

                Wieso readme? Ist das ein OSS-Projekt?

                Ich schreibe ein paar Module neu, die man wie einen Baukasten einfach zusammenstöpseln kann und dann hat man die Funktionalität, ohne verstehen zu müssen, wie es eigentlich funktioniert.

                Ich habe mich da mal an Groupwise von Novell orientiert.

                Die Idee finde ich ganz cool;)

                [..]

                Das hat immer schon ganz gut funktioniert, die Leute mussten aber immer noch viel lesen (so ca. zwei Seiten *g*), ums anwenden zu können. Das hat keiner wirklich gemacht und dann bekomme ich immer emails "wie geht das?". Das ist mir langsam zu blöd.

                Das kann ich verstehen, aber wer so etwas als Entwickler anwenden will, sollte doch schon etwas lesen können/müssen.

                Abgesehen davon: man kann wirklich nichts zu 100% idiotensicher machen - Dein Vorhaben ehrt Dich, aber ich sehe da etwas schwarz;)

                off:PP

                --
                "You know that place between sleep and awake, the place where you can still remember dreaming?" (Tinkerbell)
                1. Hallo.

                  Dein Vorhaben ehrt Dich,

                  Dein strahlender Held.

                  aber ich sehe da etwas schwarz;)

                  Dein grauer Star.
                  MfG, at

      2. Hallo,

        Ich möchte gewisse Sicherheiten herstellen. Wird ein Modul per include() und NICHT über include_once() eingebunden vom Verwender, dann soll es das Script geordnet beenden und nicht einfach mit einem redeclare-Error "abstürzen" :-)

        *SEHR* schlechte Idee. include_once() frisst Performance im Vergleich zu include() - nicht viel, aber bei 100en Dateien macht es sich z.B. bemerkbar - und wenn jemand dann aus Performancegründen im vollen Wissen, was er tut, include() statt include_once() verwendet, kackt Dein Script ab. Sehr schlechte Idee...

        Zudem: Warum überhaupt noch mit sowas rumärgern? Autoloader und gut ist...

        Viele Grüße,
        Christian

        1. Hello,

          Zudem: Warum überhaupt noch mit sowas rumärgern? Autoloader und gut ist...

          weil das OOP ist und die Module ohne auskommen sollen :-)

          Liebe Grüße aus Syburg bei Dortmund

          Tom vom Berg

          --
          Nur selber lernen macht schlau
          http://bergpost.annerschbarrich.de
  2. Hallo,

    kann man innerhalb eines PHP-Includes feststellen, ob das Include mittels include() oder mittels include_once() vorgenommen wurde?

    So, z.B. (funktioniert nur direkt im Script, nicht innerhalb einer Funktion):

    $bt = debug_backtrace ();  
    if (count ($bt)) {  
      switch ($bt[0]['function']) {  
        case 'include':  
        case 'include_once':  
        case 'require':  
        case 'require_once':  
        case 'eval':  
          // Obiges sollte alles klar sein  
          break;  
        case '__lambda_func':  
          // wurde als Funktionsrumpf in create_function gestopft, z.B. so:  
          // $foo = create_function ('',  
          //   '?>'.file_get_contents('bt2.php').'<?php ;'  
          // );  
          // Und dann als Funktion aufgerufen: $foo ();  
          break;  
        default:  
          // Unbekannter Fall. Eventuell auch wenn irgend ein Optimizer oder  
          // irgend eine komische Extension einem da reinpfuscht.  
          break;  
      }  
    } else {  
      // Script direkt aufgerufen  
    }
    

    Die Frage ist allerdings: Wozu? Ich wüßte nicht, dass das auch nur ansatzweise sinnvoll sein könnte...

    Viele Grüße,
    Christian

    1. Hello,

      erstmal danke für den Tipp.

      $bt = debug_backtrace ();

      Die Frage ist allerdings: Wozu? Ich wüßte nicht, dass das auch nur ansatzweise sinnvoll sein könnte...

      Das ist so auch nicht sinnvoll. Das hast Du Recht. die Debug-Funktionen fressen die Performance.
      Ich werde nochmal schlafen drüber, bevor ich mit den Änserungen beginne :-|

      Liebe Grüße aus Syburg bei Dortmund

      Tom vom Berg

      --
      Nur selber lernen macht schlau
      http://bergpost.annerschbarrich.de
  3. Moin!

    kann man innerhalb eines PHP-Includes feststellen, ob das Include mittels include() oder mittels include_once() vorgenommen wurde?

    Das darf also nicht in der includierenden Datei stattfinden, sondern in dem Teil, der includiert wird.

    Indem du prüfst, ob eine Konstante definiert ist, und falls nicht, sowohl die Definition der Konstanten als auch die der Funktionen vornimmst.

    if (!defined("NAMENSRAUMKONSTANTE")) {
      define("NAMENSRAUMKONSTANTE",true);
      function whatever() {}
    }

    Allerdings hast du in deinen sonstigen Äußerungen zahlreiche Ansatzpunkte für grundsätzliche Kritik an dem Projektvorhaben geliefert. Du willst ein komplexes Modulsystem erstellen - ohne OOP. Wozu der Zirkus?

    Ich hoffe, dass wenigstens für Unit-Tests gesorgt ist...

    - Sven Rautenberg

    1. Moin!

      kann man innerhalb eines PHP-Includes feststellen, ob das Include mittels include() oder mittels include_once() vorgenommen wurde?

      Indem du prüfst, ob eine Konstante definiert ist, und falls nicht, sowohl die Definition der Konstanten als auch die der Funktionen vornimmst.

      if (!defined("NAMENSRAUMKONSTANTE")) {
        define("NAMENSRAUMKONSTANTE",true);
        function whatever() {}
      }

      Alternativ kann man natürlich auch ganz sauber vorgehen, und mit function_exists() die Existenz jeder einzelnen Funktion prüfen, bevor der Code der Funktionsdefinition ausgeführt wird - falls dann doch mal eine Überlappung von Funktionsnamen passiert...

      - Sven Rautenberg

      1. Hello,

        if (!defined("NAMENSRAUMKONSTANTE")) {
          define("NAMENSRAUMKONSTANTE",true);
          function whatever() {}
        }

        Die Idee ist nach dreimal im Kreis herumdenken nicht schlecht.

        Aber:
         if (!defined("MODULKONSTANTE"))
         {
             define("MODULKONSTANTE",$versionsnummer);
             function whatever() {}
         }
         else
         {
             stop_loading();
         }

        Kann man ein Include odr ein Require denn aber überhaupt auf diese Weise noch stoppen?
        Das muss ich nachher erst einmal ausprobiern...

        Liebe Grüße aus Dortmund

        Tom vom Berg

        --
        Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Tach.

          if (!defined("NAMENSRAUMKONSTANTE")) {
            define("NAMENSRAUMKONSTANTE",true);
            function whatever() {}
          }

          Die Idee ist nach dreimal im Kreis herumdenken nicht schlecht.

          ... und sollte Dir aus den meisten C-Headerfiles bekannt vorkommen.

          Kann man ein Include odr ein Require denn aber überhaupt auf diese Weise noch stoppen?

          Du kannst return benutzen, um ins aufrufende Skript zurückzukehren.

          --
          Wenn es schwingt, ist es ein Filter – Oszillatoren würden so etwas nie tun.
          1. Hello,

            Kann man ein Include odr ein Require denn aber überhaupt auf diese Weise noch stoppen?

            Ja klar. Sorry. Ich bin im Moment auf Excel. 12 bis 16 Stunden am Tag. Das benebelt irgendwie.

            Ok, die praktischste Vorgehensweise wäre also ermittelt.

            Sven Rs Einwand verstehe ich aber nicht. Wenn ein älteres Modul bereits geladen ist (und ausreichend ist für die Funktionalität) darf über einen anderen Zweig kein neueres (das dann einen anderen Dateinamen haben könnte) mehr nachgeladen werden an einer anderes Stelle im include-Baum.

            Liebe Grüße aus Syburg bei Dortmund

            Tom vom Berg

            --
            Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
        2. Moin!

          if (!defined("NAMENSRAUMKONSTANTE")) {
            define("NAMENSRAUMKONSTANTE",true);
            function whatever() {}
          }

          Die Idee ist nach dreimal im Kreis herumdenken nicht schlecht.

          Aber:
          if (!defined("MODULKONSTANTE"))
          {
               define("MODULKONSTANTE",$versionsnummer);
               function whatever() {}
          }
          else
          {
               stop_loading();
          }

          Kann man ein Include odr ein Require denn aber überhaupt auf diese Weise noch stoppen?

          Wieso willst du es stoppen?

          Wenn per Definition gilt, dass die Konstante global eindeutig ist, und im Falle des Vorhandenseins anzunehmen ist, dass sämtliche damit verbundenen Funktionen definiert sind, dann muss nichts gestoppt werden, weil ja auch keine Fehlermeldungen auftreten: Alle gewünschten und per include (auch mehrfach) eingebundenen Funktionen existieren und können genutzt werden.

          Wenn du was stoppen und eine Fehlermeldung ausgeben wolltest, würde sich der originale Redeclare-Error ja bestens eignen.

          - Sven Rautenberg

          1. Moin.

            Wenn du was stoppen und eine Fehlermeldung ausgeben wolltest, würde sich der originale Redeclare-Error ja bestens eignen.

            Wie wäre es mit folgender Variante, die beim Versuch des Einbindens einer anderen Modulversion eine Exception wirft und bei gleicher Version stillschweigend voranschreited?

              
            // 0x200901a1 ist die Versions-ID des Moduls  
              
            if(defined('MODULE_CONST')) {  
                if(MODULE_CONST !== 0x200901a1)  
                    throw new Exception('trying to re-include incopatible version of $module');  
            }  
            else {  
                define('MODULE_CONST', 0x200901a1);  
                // [...]  
            }  
            
            

            Christoph

  4. Moin.

    kann man innerhalb eines PHP-Includes feststellen, ob das Include mittels include() oder mittels include_once() vorgenommen wurde?

    Was spricht denn gegen die Verwendung von inclusion guards, wie man sie aus C header-Dateien kennt und die bewirken, dass diese beliebig oft eingebunden, aber nur einmalig ausgewertet werden können?

    Beispiel:

      
    // --- lib.php --  
      
    if(!isset($lib_included)) {  
      
        $lib_included = true;  
      
        function hw() {  
            echo 'hello world';  
        }  
      
    }  
    
    
      
    // --- test.php ---  
      
    include('lib.php');  
    include('lib.php');  
      
    hw();  
    
    

    Christoph

    1. Moin.

      Irgendwie muss ich wohl Sven's Nachricht überlesen haben, die den 'richtigen Weg' über Konstanten geht. Um meiner Antwort wenigstens etwas Sinn zu geben, habe ich eine kleine Laufzeitmessung durchgeführt.

      Ergebnis: die Nutzung von Variablen ist im Mittel /minimal/ schneller als die Nutzung von Konstanten. Beide Varianten sind aber langsamer als include\_once...

      inclusion guard, define : 4.39391684532s
      inclusion guard, $var   : 4.14313602448s
      include_once            : 3.12141108513s

      Christoph

      1. Moin!

        Irgendwie muss ich wohl Sven's Nachricht überlesen haben, die den 'richtigen Weg' über Konstanten geht. Um meiner Antwort wenigstens etwas Sinn zu geben, habe ich eine kleine Laufzeitmessung durchgeführt.

        Ergebnis: die Nutzung von Variablen ist im Mittel /minimal/ schneller als die Nutzung von Konstanten. Beide Varianten sind aber langsamer als include\_once...

        Die Nutzung mit Variablen garantiert aber nicht, dass das Include nur einmal ausgeführt wird, da man Variablen ja auch wieder löschen kann. Außerdem verschmutzen sie den globalen Namensraum für Variablen - das mag zwar nur eine Unschönheit sein, der man durch Wahl eines geeignet langen Variablennamens begegnen kann, aber es ist trotzdem blöd.

        - Sven Rautenberg

        1. Hello,

          die Nutzung von Konstanten finde ich am praktischsten. Sie lassen sich nicht überschreiben und geben so einen gewissen Schutz, dass ein Modul nicht zweimal geladen wird.

          Das eigentliche Problem wird dabei dann auch beseitigt, nämlich dass ein Modul in zwei verschiedenen Versionen geladen werden kann. Die beiden Versionen hätten dann sicherlich unterschiedliche Namen, aber (vorausgestzt, sie kommen aus demselben Hause) dieselbe Konstante für die Modulkennung.

          Da die Module in unterschiedlichen Versionen aber garantiert noch (einige) gleichnamige Funktionen enthalten würden, würde ein include_once() trotzdem nicht vor einem Redeclare Error schützen.

          Also nur noch mit include() oder require einbinden und den Einbindevorgang gleich am Anfang abwürgen, wenn die Modulkonstante schon existiert.

          Liebe Grüße aus Syburg bei Dortmund

          Tom vom Berg

          --
          Nur selber lernen macht schlau
          http://bergpost.annerschbarrich.de