mysqli und output buffering

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • mysqli und output buffering

    In nachfolgendem Skript ist die globale Variable $db innerhalb der ob-routine "layout" nicht definiert, obwohl sie das meiner Meinung nach sein müsste. Mit anderen Variablen funktioniert es, und auch, wenn ich mysqli_connect durch mysql_connect ersetze. Muss also irgendwie an mysqli liegen, aber ich konnte dazu im Netz nichts finden.

    Ausgabe:

    Code:
    db outside: set
    test outside: set
    db inside: unset
    test inside: set
    Und hier der Code:

    PHP-Code:
    <?php

    ob_start
    ("layout");

    $db mysqli_connect('localhost''xxx''xxx''xxx');
    $test '123';

    error_log('db outside: '.(isset($db)?"set":"unset"));
    error_log('test outside: '.(isset($test)?"set":"unset"));

    function 
    layout($s)
    {
        global 
    $db,$test;
        
        
    error_log('db inside: '.(isset($db)?"set":"unset"));
        
    error_log('test inside: '.(isset($test)?"set":"unset"));
        
        return 
    $s;
    }

    ?>
    Hat jemand eine Idee, woran das liegt? Oder ist es ein Bug in mysqli?

    PS: Ich verwende PHP-Version 5.6.17-0+deb8u1
    Zuletzt geändert von berni15; 09.02.2016, 14:49. Grund: PHP-Version hinzugefügt

  • #2
    global ist böse und sollte nicht verwendete werden.

    Datenbankabfragen haben innerhalb der Ausgabe nichts verloren, bitte beachte das EVA-Prinzip.

    Kommentar


    • #3
      Zitat von h3ll Beitrag anzeigen
      global ist böse und sollte nicht verwendete werden.
      Tja, bei großen, alten Projekten hat man halt nicht die Wahl. Umstellen ist zu aufwendig. Dann muss man halt damit leben. Ohne den obigen Bug würde ich übrigens mit genau der einen globalen Variablen auskommen. Jetzt muss ich die ganzen Daten schon vorab runterladen, selbst wenn sie gar nicht gebraucht werden, und in globale Variablen stecken, damit ich sie dann während der Ausgabe zur Verfügung habe. Ich finde das nicht besser.

      Datenbankabfragen haben innerhalb der Ausgabe nichts verloren, bitte beachte das EVA-Prinzip.
      Das EVA-Prinzip ist halt ein Prinzip. Da kann man sich dran halten, muss man aber nicht. Ich halte es jedenfalls für einen deutlich größeres Problem, wenn in einer Programmiersprache plötzlich Variablen einfach so den Houdini machen können. Da kann man sich ja auf gar nichts mehr verlassen...

      Kommentar


      • #4
        Zitat von berni15 Beitrag anzeigen
        Das EVA-Prinzip ist halt ein Prinzip. Da kann man sich dran halten, muss man aber nicht. Ich halte es jedenfalls für einen deutlich größeres Problem, wenn in einer Programmiersprache plötzlich Variablen einfach so den Houdini machen können. Da kann man sich ja auf gar nichts mehr verlassen...
        Das erfordert eben größere Selbstdisziplin. Wenn man sich auf die Programmiersprache nicht verlassen kann, muss man sich eben auf den Programmierer verlassen. Und da ist es nicht förderlich, wenn man schlampig arbeitet und alle Prinzipien über Bord wirft, weil man meint, dass sie für einen selber nicht gelten.

        Kommentar


        • #5
          Die Sache ist, dass diese „passiert am Ende des Scripts automatisch“-Geschichten in PHP nicht unbedingt in der Reihenfolge ablaufen, die man „erwarten“ würde.

          Hier scheint es der Fall zu sein, dass die Garbage Collection zuerst läuft oder dass zumindest zuerst die Objekte aus dem Speicher freigegeben werden, bevor das Callback ausgeführt wird. (Das liegt nicht speziell an mysqli. Das liegt daran, dass mysqli-Instanzen Objekte sind, während mysql-„Instanzen“ Ressourcen sind.)

          Lösungen:

          - Beende den Output Buffer manuell am Scriptende via ob_get_clean und Co.
          - Sichere die benötigten Variablen in einer Closure. (Das ist dann allerdings der Inhalt der Variablen zu dem Zeitpunkt der Erstellung der Closure.)

          PHP-Code:
          <?php

          $db 
          mysqli_connect('localhost''root''root''fiddle');
          $test '123';

          $cb = function ($s) use ($db$test) {

              
          error_log('db inside: '.(isset($db)?"set":"unset"));
              
          error_log('test inside: '.(isset($test)?"set":"unset"));

              return 
          $s;
          };

          ob_start($cb);

          error_log('db outside: '.(isset($db)?"set":"unset"));
          error_log('test outside: '.(isset($test)?"set":"unset"));
          Zuletzt geändert von mermshaus; 24.02.2016, 13:08.

          Kommentar


          • #6
            Zitat von mermshaus Beitrag anzeigen
            Hier scheint es der Fall zu sein, dass die Garbage Collection zuerst läuft oder dass zumindest zuerst die Objekte aus dem Speicher freigegeben werden, bevor das Callback ausgeführt wird. (Das liegt nicht speziell an mysqli. Das liegt daran, dass mysqli-Instanzen Objekte sind, während mysql-„Instanzen“ Ressourcen sind.)
            Das erklärt's.

            Lösungen:

            - Beende den Output Buffer manuell am Scriptende via ob_get_clean und Co.
            - Sichere die benötigten Variablen in einer Closure. (Das ist dann allerdings der Inhalt der Variablen zu dem Zeitpunkt der Erstellung der Closure.)
            Ersteres ist für mich keine sinnvolle Lösung, weil ich OB ja gerade dafür verwende, damit ich nicht am Ende jedes Skripts manuell nochmal eine Funktion aufrufen muss, sondern das einmal zentral verwalten kann. - Gibt's da eigentlich eine Alternativen, also einen Hook, der ausgeführt wird, denn das PHP-Skript ansonsten zu Ende ist? Das wäre dann vielleicht eine bessere Lösung als OB.

            Zweiteres tut, aber es fühlt sich für mich irgendwie nicht gut an. Wer weiß, ob da nicht doch irgendwann noch irgendwas anderes von der GC abgeholt wird, bevor es verwendet wird.

            Danke dir jedenfalls für die Antwort.

            PS: Eigentlich ist der Thread ja nun im falschen Forum gelandet, weil es mit Datenbanken gar nichts zu tun hat. Sollte man ihn verschieben?!?

            Kommentar


            • #7
              Gibt's da eigentlich eine Alternativen, also einen Hook, der ausgeführt wird, denn das PHP-Skript ansonsten zu Ende ist?
              Es gäbe noch register_shutdown_function und auto_append_file. Ob es dabei ähnliche Probleme gibt, weiß ich nicht.

              Kommentar


              • #8
                Zitat von mermshaus Beitrag anzeigen
                Es gäbe noch register_shutdown_function und auto_append_file. Ob es dabei ähnliche Probleme gibt, weiß ich nicht.
                Beim Testen waren bei register_shutdown_function noch alle Variablen da. Zusammen mit ob_get_clean ist das für mich die perfekte Lösung - besser als voher! Danke dir nochmal.

                Kommentar

                Lädt...
                X