PHP Fatal error: Uncaught Error: Call to a member function query() on null in
Jörg
- mysql
Hallo,
ein Code, der auf meinem php 8.1 Testsystem keinen Fehler auswirft, macht das auf meinem php 8.1 Produktivsystem.
try {
$db = new PDO("mysql:host =$server;dbname=$name;charset=utf8;port=3306",$user,$passwd);
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
} catch (PDOException $e) {
echo 'Verbindung fehlgeschlagen: ' . $e->getMessage();
}
$query_ma = "SELECT ID,User FROM myuser";
$result_ma = $db->query($query_ma);
ergibt auf dem Produktivsystem:
PHP Fatal error: Uncaught Error: Call to a member function query() on null in ...
Weiß grad gar nicht, was php zu meckern hat?
Wersagts mir?
Jörg
Hallo Jörg,
dann ist $db auf null.
Steht da "Verbindung fehlgeschlagen"? Oder eine andere Fehlermeldung? Hast Du display_errors mal eingeschaltet und error_reporting aufgedreht?
Ich kann mir nur vorstellen, dass der new PDO schiefgeht, deswegen $db nicht initialisiert ist und null enthält.
Du hast zwar einen try/catch drin, aber der catch-Block lässt den Code munter weiterlaufen. Das ist nicht der Sinn des Errorhandlings. Code, der wegen eines Errows keinen Sinn mehr ergibt, darf nicht ausgeführt werden.
Vielleicht fliegt ja auch eine andere Exception. Du könntest einen zweiten Catch-Block für Throwable $t anhängen, falls Du "Verbindung fehlgeschlagen" nicht siehst.
try {
$db = new PDO(...);
}
catch (PDOException $ex) {
...
}
catch (Throwable $unknownError) {
echo "General Failure übernimmt das Kommando\n";
echo $unknownError;
}
Rolf
Wenn der Fehler in der Zeile ...
$result_ma = $db->query($query_ma);
bekrittelt wird, dann hat $db = new PDO( ... )
wohl keinen Fehler (genauer PDOException) geschmissen - aber NULL
geliefert.
Prüfe, warum das so ist.
Hallo Raketenwilli,
dann hat $db = new PDO( ... ) wohl keinen Fehler geschmissen - aber NULL geliefert.
Geht das? Das ist ein new Operator, und den kannst Du nur dadurch vom Liefern eines Objekts abhalten, indem Du ihm eine Exception an den Kopf wirfst.
Rolf
Hallo Rolf, Hallo Willi,
ja, Ihr hattet recht, die Verbindung zur db war auf dem Produktivsystem nicht vorhanden.
Und warum beim Verbindungsaufbau kein Fehler geworfen wurde, ist auch klar. Mein Code, den ich gepostet hatte, war gut, aber der auf dem Server war leider etwas anders.
try {
$db = new PDO("mysql:host =$server;dbname=$name;charset=utf8;port=3306",$user,$passwd);
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
} catch (PDOException $e) {
echo 'Verbindung fehlgeschlagen: ' . $e->getMessage();
}
$query_ma = "SELECT ID,User FROM myuser";
$result_ma = $dbo->query($query_ma);
Das klärt es auf 😉
Danke für Eure Hilfe,
Jörg
Hallo nochmal,
nachdem vorhin ja recht schnell klar war, wo der Fehler lag, finde ich ihn nun schon wieder nicht.
In meiner Konfigurationsdatei connecte ich meine DB.
Dann sollte doch die Verbindung in einem Script, das diese Konfigurationsdatei includet, noch erhalten bleiben, hm?
Frage: Wie kann ich abfragen, ob die Verbindung noch besteht? Meine Idee ist, ich will erruieren, wo sie verloren geht.
Jörg
In meiner Konfigurationsdatei connecte ich meine DB.
Dann sollte doch die Verbindung in einem Script, das diese Konfigurationsdatei includet, noch erhalten bleiben, hm?
Aber ja. Bis Du die Variable oder Verbindung wegschmeisst. Es sei denn, Du findest diese nur nicht.
require
oder require_once
statt include
.$GLOBALS['db']
).$GLOBALS['db']
).Hallo Willi,
- Was steht im error.log?
Da stand wirklich nur das drin, was ich hier in der Threadüberschrift gewählt hatte. Aber seltsamerweise habe ich die beiden Stellen (in 2 verschiedenen Scripten) dann mal mit einem weiteren iclude_once() bestückt, woraufhin der Fehler verschwand. Dann habe ich das (IMHO überflüssige) include_once() wieder gelöscht und php hatte ein Einsehen... die Fehlermeldung blieb aus. Seltsam...
- Wird die Konfigurationsdatei wirklich geladen? - Versuche
require
oderrequire_once
stattinclude
.
Na sollte schon.
Weil ich nutze die Anwendung schon seit jahren, nur eben auf php7.
- Erfolgt der connect innerhalb einer Funktion, einer Methode oder dergleichen? -
Nein, darauf hatte ich geachtet, ob die Variablen innerhalb ihres Gültigkeitsraumes waren.
Gib das DB/PDO-Object mit return zurück oder schreib es in den globalen Raum (e.g.
$GLOBALS['db']
).
Wie macht man das genau?
Weil, genau das hätte ich gebraucht.
Jetzt läuft es zwar prima, aber fürs nächste mal wärs gut, wenn ich wüßte, wie man das genau notieren muss.
- Wenn Du innerhalb von anderen Funktionen oder Methoden nicht auf Dein Datenbankobjekt zugreifen kannst, dann übergib es der Funktion oder lese es aus dem globalen Raum (e.g.
$GLOBALS['db']
).
Ja, das hätte ich aber gefunden. Wie schon gesagt, Gültigkeitsraum von Variablen ist mir schon ein begriff.
Danke für die Hilfe, Jörg
Gib das DB/PDO-Object mit return zurück oder schreib es in den globalen Raum (e.g. $GLOBALS['db']).
Wie macht man das genau?
1_Beispiel->sagt() > 1000_Worte->sagt()
:
<?php
$GLOBALS['ZumGruß'] = 'Hallo Welt!';
function GlobalZumGruß() {
echo $GLOBALS['ZumGruß'] . PHP_EOL;
}
GlobalZumGruß();
$ZumGruß = 'Grüß Gott!';
function GlobalGrüßGott() {
echo $GLOBALS['ZumGruß'] . PHP_EOL;
}
GlobalGrüßGott();
GlobalZumGruß();
ausführen …
Hallo Welt!
Grüß Gott!
Grüß Gott!
Also ... ganz einfach: $GLOBALS['ZumGruß']
und $ZumGruß
im globalen Namensraum sind sozusagen das selbe.
Hinweis:
Eigentlich ist die Verwendung von $GLOBALS
ein „Hirnfurz“, weil das die Klarheit beseitigt, was in den Variablen steht.
Alternative? Konstanten:
define (
'FH',
fopen( __FILE__, 'r' )
);
$i=0;
while( $row = fgets( FH ) ) {
echo ( $i++ ) . "\t" . htmlspecialchars( $row );
}
Benutze also die Konstante wie gezeigt. Die sind in PHP immer global.
Hallo Raketenwilli,
statt $_GLOBALS kann man auch das global Statement verwenden. Die Frage ist natürlich, ob diese $db Variable überhaupt global war.
Edit: Die Variable heißt natürlich $GLOBALS 😕
Einen define für eine DB Connection kann man aber nicht verwenden. Weil das eben keine Konstante ist, sondern ein Objekt. Oder was sollte dein Beispiel besagen? Ich sehe da Code, der seinen eigenen Sourcecode ausgibt...
Rolf
Hi Rolf,
statt $_GLOBALS kann man auch das global Statement verwenden. Die Frage ist natürlich, ob diese $db Variable überhaupt global war.
So mache ich es übrigens bisher.
Jörg
Einen define für eine DB Connection kann man aber nicht verwenden. Weil das eben keine Konstante ist, sondern ein Objekt.
Ok. Ich zeige es.
<?php
define(
'sqlite3',
new SQLite3( '/home/fastix/armbian.sqlite3' )
);
$query = 'SELECT name, description from pakete LIMIT 4';
$result = sqlite3->query( $query );
while ( $row = $result->fetchArray( SQLITE3_ASSOC ) ) {
print_r( $row );
};
... Dann sollte man das testen.
Array
(
[name] => accountsservice
[description] => query and manipulate user account information
)
Array
(
[name] => acct
[description] => GNU Accounting utilities for process and login accounting
)
Array
(
[name] => acl
[description] => access control list - utilities
)
Array
(
[name] => acpid
[description] => Advanced Configuration and Power Interface event daemon
)
Oder was sollte dein Beispiel besagen? Ich sehe da Code, der seinen eigenen Sourcecode ausgibt...
und jetzt die ersten vier Zeilen aus der Liste der Pakte von Armbian.
Erst wenn ich an das Skript
sqlite3->close();
$result = sqlite3->query( $query );
anhänge (also die Verbindung schließe und die Abfrage nochmals versuche), dann kommt
PHP Fatal error: Uncaught Error: The SQLite3 object has not been correctly initialised or is already closed in /home/fastix/tmp/2.php:14
Also in der Zeile $result = sqlite3->query( $query );
ich hätte auch erwartet, dass PHP sich dort über die geschlossene Verbindung beschwert.
sqlite->open( $file );
funktioniert auch.
Hallo Raketenwilli,
ich hatte es nie ausprobiert. Ich weiß nur, was im Handbuch steht:
new PDO(...) oder new SQLite3 liefert ein Objekt. Das ist kein Skalar und kein Array, es kommt vermutlich einer Ressource näher. Und deswegen bin ich davon ausgegangen, dass man das lassen sollte. Die Warnung steht bestimmt nicht zum Spaß im Handbuch. Leider erklärt sie nicht, was genau das Problem sein kann.
Rolf
Die Warnung steht bestimmt nicht zum Spaß im Handbuch.
Oder jemand war zu faul. Oder es funktioniert nicht wie vom Autor ursprünglich geplant…
Leider erklärt sie nicht, was genau das Problem sein kann.
Naja. Erklär mal einem Leser, warum bei einem als Konstante instanzierten Objekt Eigenschaften sehr wohl mit einem Setter (und durch andere Objekt-Methoden) geändert werden können, nicht aber direkt.
Und naja. Wenn sich ein Objekt mal so und mal so verhält, dann ist das verwirrend. Das ist wohl mit „nicht vorhersehbar“ gemeint. Ansonsten ist es Eigenschaft eines Programmes, dass es sich (abgesehen von der Generierung von Zufallswerten) stets gleich verhält. Man könnte das also dokumentieren.
<?php
class Foo {
var $foo = 0;
var $bar = 0;
function __construct( $foo, $bar ) {
$this->foo = $foo;
$this->bar = $bar;
}
function setFoo( $v ) {
$this->foo = $v;
}
function setBar( $v ) {
$this->bar = $v;
}
}
define (
'Objekt',
new Foo(1,1)
);
echo 'Objekt->foo : ' . Objekt->foo . PHP_EOL;
echo 'Objekt->bar : ' . Objekt->bar . PHP_EOL;
### Das geht nicht:
#Objekt->bar=2;
#Objekt->bar=2;
#echo 'Objekt->foo : ' . Objekt->foo . PHP_EOL;
#echo 'Objekt->bar : ' . Objekt->bar . PHP_EOL;
### Mit den Settern geht es aber:
Objekt->setFoo(2);
Objekt->setBar(2);
echo 'Objekt->foo : ' . Objekt->foo . PHP_EOL;
echo 'Objekt->bar : ' . Objekt->bar . PHP_EOL;
Objekt->foo : 1
Objekt->bar : 1
Objekt->foo : 2
Objekt->bar : 2
Fazit: Sogar Eigenschaften eines Objektes sind auch dann veränderlich, wenn das Objekt als Konstante abgelegt wurde. Aber nur mittels einer Objekt-Methode wie den gezeigten Settern.
statt $_GLOBALS kann man auch das global Statement verwenden.
Ja. Auch der Mist geht. Das die Variable $GLOBALS
heißt ist auch so ein „Hirnfurz“: Superglobale Variablen sind $_SERVER
, $_GET
, $_POST
, $_FILES
,
$_COOKIE
, $_SESSION
, $_REQUEST
, $_ENV
und dann („Peng!“) $GLOBALS
!
Wenn ich ganz ehrlich bin, dann bin ich „nicht besonders hell begeistert“, wenn man in Programmiersprachen ein- und das selbe auf gefühlte 16.389 Weisen machen kann. Diese ganzen Aliase und Alternativen (mit teilweise kruden Schreibweisen) muss man zwar nicht selbst benutzen, aber wahrscheinlich lesen.
Und für die zugehörigen Parser, Linter, Interpreter oder Kompiler gilt das letztendlich auch. Mir kann keiner erzählen, dass eine solche Alternativenwulst die Ausführung von Skripten schneller macht und auch nur irgendwas vereinfacht. Ich denke, da werden einfach Designfehler der Programmiersprache („Hirnfürze“) konserviert.
Zur Berechnung im Titel:
„Nur“ 100 Items, welche die Kompilierungs- oder Ausführungszeit eines Programmes jeweils um „unbeachtliche“ 0,5% erhöhen, machen es im schlimmsten Fall so langsam, dass es die 1,646-fache Zeit braucht…
Erstmal 1000 Dank, Willi! 👍
1_Beispiel->sagt() > 1000_Worte->sagt()
:
Wem sagst Du das?
meineRede = 1_Beispiel->sagt() > 1000_Worte->sagt(); 😅
Hinweis:
Eigentlich ist die Verwendung von
$GLOBALS
ein „Hirnfurz“, weil das die Klarheit beseitigt, was in den Variablen steht.
Stimmt, aer war trotzdem ein gutes Beispiel, weil nochmal klar gemacht hat, worauf Du hinaus wolltest.
Alternative? Konstanten:
define ( 'FH', fopen( __FILE__, 'r' ) ); $i=0; while( $row = fgets( FH ) ) { echo ( $i++ ) . "\t" . htmlspecialchars( $row ); }
Benutze also die Konstante wie gezeigt. Die sind in PHP immer global.
Sehr gute Idee. Werde ich machen, bzw. mache ich heute auch schon, nämlich arbeite ich in Datenbanken eigentlich immer mit Tabellenpräfixen... und genau da nutze ich immer Konstanten.
Und, ich muss es zugeben, bei nder Umstellunmg von php7 auf php8 nutze ich grad auch Konstanten, weil ich sehr, sehr oft in Funktionsaufrufen die Anführungszeichen bei Stringparametern weggelasen habe. Und da hab ich jetzt (erstmal) eine Handvoll Strings als Konstanten declariert, damit mir nihct bei jedem 2. Schritt meine Anwendung mit FatalError abschmiert.
Jörg
Hi,
try { $db = new PDO("mysql:host =$server;dbname=$name;charset=utf8;port=3306",$user,$passwd); $db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); } catch (PDOException $e) { echo 'Verbindung fehlgeschlagen: ' . $e->getMessage(); } $query_ma = "SELECT ID,User FROM myuser"; $result_ma = $db->query($query_ma);
ist nicht wirklich sinnvoll - wenn die Verbindung fehlschlägt, wird eine Meldung ausgegeben, aber danach munter weiter auf die Verbindung zugegriffen.
PHP Fatal error: Uncaught Error: Call to a member function query() on null in ...
Weiß grad gar nicht, was php zu meckern hat?
Wersagts mir?
PHP hat's Dir doch gesagt: das Objekt, auf dem Du query aufrufst (also $db), ist null.
cu,
Andreas a/k/a MudGuard