PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr

PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr (https://www.php-resource.de/forum/)
-   SQL / Datenbanken (https://www.php-resource.de/forum/sql-datenbanken/)
-   -   mysqli und output buffering (https://www.php-resource.de/forum/sql-datenbanken/105482-mysqli-und-output-buffering.html)

berni15 09-02-2016 14:47

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

h3ll 09-02-2016 16:17

global ist böse und sollte nicht verwendete werden.

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

berni15 23-02-2016 17:55

Zitat:

Zitat von h3ll (Beitrag 672313)
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.

Zitat:

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...

h3ll 23-02-2016 18:01

Zitat:

Zitat von berni15 (Beitrag 672411)
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.

mermshaus 24-02-2016 13:04

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"));


berni15 24-02-2016 16:08

Zitat:

Zitat von mermshaus (Beitrag 672415)
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.

Zitat:

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?!?

mermshaus 24-02-2016 17:47

Zitat:

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.

berni15 24-02-2016 20:29

Zitat:

Zitat von mermshaus (Beitrag 672428)
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.


Alle Zeitangaben in WEZ +2. Es ist jetzt 18:03 Uhr.

Powered by vBulletin® Version 3.8.2 (Deutsch)
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0
[c] ebiz-consult GmbH & Co. KG