Geltungsbereich Variable in Funktion
Pit
- php
Hallo,
ich möchte gerne den Verbindungsaufbau zur DB (pdo) über meine config-datei erledigen, weil die ohnehin bei jedem Script aufgerufen wird.
Aufbau:
$user="root";
$passwd="";
$server="localhost";
$name="table";
try {
$mydb = new PDO("mysql:host=".$server.";dbname=".$name.";charset=utf8;port=3306",$user,$passwd);
$mydb->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
} catch (PDOException $e) {
echo 'Verbindung fehlgeschlagen: ' . $e->getMessage();
}
Leider ergibt das in jeder Funktion aber einen Fehler, weil dort die Verbindung nicht bekannt ist. Wenn ich innerhalb der Funktion die config wieder include, dann läufts.
Fehler: Fatal error: Call to a member function query() on a non-object in...
Kann man das erneute includen in jede Funktion irgendwie umgehen?
Pit
Hallo
ich möchte gerne den Verbindungsaufbau zur DB (pdo) über meine config-datei erledigen, weil die ohnehin bei jedem Script aufgerufen wird.
Aufbau:
try { $mydb = new PDO("mysql:host=".$server.";dbname=".$name.";charset=utf8;port=3306",$user,$passwd); $mydb->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); } catch (PDOException $e) { echo 'Verbindung fehlgeschlagen: ' . $e->getMessage(); }
Leider ergibt das in jeder Funktion aber einen Fehler, weil dort die Verbindung nicht bekannt ist. Wenn ich innerhalb der Funktion die config wieder include, dann läufts.
Fehler: Fatal error: Call to a member function query() on a non-object in...
Kann man das erneute includen in jede Funktion irgendwie umgehen?
Übergib das Verbindungsobjekt $mydb
als Parameter in die Funktionen.
Tschö, Auge
Hi Auge,
Kann man das erneute includen in jede Funktion irgendwie umgehen?
Übergib das Verbindungsobjekt
$mydb
als Parameter in die Funktionen.
Ersteinmal danke für Deine Hilfe.
Leider bringt mir das nicht ganz so viel, weil es für mich noch mehr Arbeit bedeuten würde.
Hintergrund: Ich bin dabei, meine scripte von mysql_ nach PDO umzuschreiben. Bei Deiner Lösung müßte ich nun auch noch alle Funktionsaufrufe berücksichtigen.
Kann ich das umgehen? Ggf. durch Anhang des Parameters mit einem Defaultwert?
Oder soll kann man (und sollte man überhaupt??) das Objekt auf global setzen?
Pit
Hallo,
Übergib das Verbindungsobjekt $mydb als Parameter in die Funktionen
Kann man machen, ist aber extrem lästig.
Man kann für solche zentralen Singletons durchaus auch global verwenden.
Es gibt nach meiner Meinung 4 Ansätze für SQL in Programmen:
Rolf
Hallo
Übergib das Verbindungsobjekt $mydb als Parameter in die Funktionen
Kann man machen, ist aber extrem lästig.
Man kann für solche zentralen Singletons auch global verwenden.
Kann man natürlich auch machen. Das habe ich aber bewusst unterschlagen, weil die Nennung bei mir eine gewisse Enge in den Schuhspitzen erzeugt. Ich mag's halt nicht.
<buzzwordstream>
Oder man lernt Begriffe wie Inversion-of-Control und Dependency Injection, und injiziert sich das DB-Zugriffsobjekt in die Arbeitsklassen. Ist aber nicht so ganz aus dem Handgelenk erledigt...
</buzzwordstream>
Oder so, aber dazu kann ich nichts beitragen.
Tschö, Auge
Tach!
Kann man das erneute includen in jede Funktion irgendwie umgehen?
Um auf globale Variablen in Funktionen zuzugreifen, muss man diese dort entweder mit dem Schlüsselwort global bekanntgeben, oder man greift über das $GLOBALS-Array zu, das ist superglobal und von überall ansprechbar.
Schön ist diese Vorgehensweise aber nicht. Man muss vor dem Funktionsaufruf wissen, was man erst zu initialisieren hat, damit die Funktion arbeiten kann. Besser ist es, man fordert die Abhängigkeiten über Parameter ein, damit man das nicht vergessen kann. Man nennt das Dependency Injection. Allerdings ist das dann auch Arbeit, die Abhängigkeiten herumzureichen. Und so hat man Dependency-Injection-Frameworks entwickelt, die einem die Arbeit größtenteils abnehmen. Lohnt sich aber erst ab großen Projekten, wenn es nicht bereits im sowieso schon verwendeten Framework enthalten ist.
dedlfix.
Hello,
Um auf globale Variablen in Funktionen zuzugreifen, muss man diese dort entweder mit dem Schlüsselwort global bekanntgeben, oder man greift über das $GLOBALS-Array zu, das ist superglobal und von überall ansprechbar.
Oder man baut sich ein Singleton, was ja dank Static-Variablen auch in der prozeduralen Programmierung von PHP geht. Das hat den Vorteil, dass sie Bestand hat, wenn sie einmal gesetzt wurde.
Ist später die Variable === NULL, existiert keine DB-Connection.
Liebe Grüße
Tom S.
Moin Pit,
was passiert denn mit folgender kleiner Änderung?
$user="root"; $passwd=""; $server="localhost"; $name="table"; $mydb = NULL; // ← beachte try { $mydb = new PDO("mysql:host=".$server.";dbname=".$name.";charset=utf8;port=3306",$user,$passwd); $mydb->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); } catch (PDOException $e) { echo 'Verbindung fehlgeschlagen: ' . $e->getMessage(); }
… und dann in deiner Funktion
function something(/* possible parameters */) {
global $mydb;
}
Viele Grüße
Robert
Lieber Pit,
die Lösung mit global
hat man Dir ja schon angeboten. Aber dazu wurde auch gesagt, dass das nicht optimal ist. Wie aber kann man die Idee mit dem globalen Zugriff auf eine Variable besser lösen?
Wenn man sein Programm als großes Objekt definiert, dann kann man in diesem Objekt sogenannte Eigenschaften definieren. Innerhalb des Objekts sind diese Eigenschaften wie globale Variablen verfügbar.
Vergleiche:
$myVar = 3;
function say () {
global $myVar;
echo $myVar;
}
class MyProgram {
private $myVar = 3;
public function say () {
echo $this->myVar;
}
}
$myProgram = new MyProgram;
$myProgram->say();
Klar, für dieses klitzekleine Beispiel ist der Schreibaufwand mit einer globalen Variable viel geringer. Aber je größer ein Projekt wird, desto besser gelingt es den Überblick zu behalten, wenn es in objektorientierter Weise modularisiert wird.
Jetzt möchtest Du eine PDO-Instanz nutzen. Da hast Du schon ein Objekt. Warum packst Du es nicht als eine Eigenschaft in Dein zum Objekt umgewandeltes Programm? Anstatt $myVar
könntest Du $this->db
verwenden - oder so.
Liebe Grüße,
Felix Riesterer.
... übrigens:
Dieses Problem habe ich nur bei der PDO-Lösung gehabt.
Bei der ursprünglichen mysql_ - Lösung ist die Verbindung "bekannt".
Wie kommt das eigentlich?
Pit
Tach!
Bei der ursprünglichen mysql_ - Lösung ist die Verbindung "bekannt".
Wie kommt das eigentlich?
Weil man das so programmiert hat. Wenn keine Verbindungskennung den Funktionen übergeben wurde, hat PHP eine der bereits geöffneten verwendet.
dedlfix.
Weil man das so programmiert hat. Wenn keine Verbindungskennung den Funktionen übergeben wurde, hat PHP eine der bereits geöffneten verwendet.
Danke dedlfix,
hat das prozedurale mysqli das auch übernommen?
Pit
Tach!
hat das prozedurale mysqli das auch übernommen?
Nein, deswegen musst du es ja zu jedem Funktionsaufruf angeben. Während es bei mysql ein optionaler Parameter war, der an letzter Stelle stand, ist es bei mysqli der erste und ein Pflichtparameter.
dedlfix.