"MySql Link" als Parameter weitergeben
Matthias
- php
Hallo miteinander!
Ich bin gerade dabei, mir Klassen für den Datenbankzugriff auf MySql zu basteln.
Die Struktur sieht wie folgt aus (vereinfacht):
Ich erstelle eine neue Datenbank, indem ich die Klasse "Database" instanziere:
$db = new Database("localhost", "root", "***", "datenbank");
Der Konstruktor der Klasse verbindet zur Datenbank und legt die Verbindungskennung im Member "resource" ab:
// Connect to MySql server
$this->resource = @mysql_connect($_host, $_user, $_password);
if(!$this->resource)
throw new SqlException("Connection failed");
// Select database
if(!@mysql_select_db($_database, $this->resource))
throw new SqlException("Database selection failed");
Ich habe nun also eine Verbindung zur Datenbank und die Verbindungskennung gespeichert.
Nun will ich ein neues Query absetzen, das ganze funktioniert so:
$query = $db->query("SELECT * FROM test");
Die Funktion "query" erstellt ein neues Objekt vom Typ "Query" und übergibt dabei den Querystring und die Verbindungskennung:
return new Query($_query, $this->resource);
Im Konstruktor von "Query" wird dieses direkt ausgeführt:
// Execute query
$this->query = @mysql_query($_query, $_resource);
// Throw exception if query was not successful
if($this->query == null) throw new SqlException("Query failed", $_query);
Allerdings ist $_resource innerhalb dieser Funktion keine gültige Verbindungskennung und führt zu einem Fehler. Bei Verwendung innerhalb der Klasse "Database" gibt es keine Probleme. Erst wenn die Verbindungskennung an das neue "Query" Objekt übergeben wird. Auch die Übergabe als Referenz hat nichts daran geändert.
Führe ich var_dump() für den Member "resource" aus, so bekomme ich innerhalb der Klasse "Database" folgende Ausgabe:
resource(9) of type (mysql link)
resource(9) of type (mysql link)
In der Klasse "Query" gibt das selbe folgende Ausgabe:
resource(9) of type (mysql link)
NULL
Ich weiß nicht mehr was ich noch versuchen soll, kann man diese Verbindungskennung etwa nicht übergeben? Ich würde dies nämlich gerne so machen, dass später auch einmal zwei Datenbanken parallel eingesetzt werden können.
Vielleicht hatte ja schonmal jemand das selbe Problem oder erkennt beim ersten Blick woran es liegt ;)
Danke schonmal für die Mühe!
Schöne Grüße,
Matthias
hi Matthias,
Vielleicht hatte ja schonmal jemand das selbe Problem oder erkennt beim ersten Blick woran es liegt ;)
Weder, noch... aber ich vermute mal, dass du bei einem der beiden funktionsaufrufe den parameter falsch übergibst. es wäre hilfreich, einmal den ganzen code (oder zumindest die relevanten ausschnitte) zu posten, dann können wir das besser analysieren
Gruß,
Niklas
Danke schonmal für deine Antwort!
Anbei etwas größere Ausschnitte des Codes, viel mehr sollte dafür ja aber eigentlich nicht relevant sein:
Klasse Database
---------------
class Database {
private $resource = null;
public function __construct($_host, $_user, $_password, $_database) {
// Connect to MySql server
$this->resource = @mysql_connect($_host, $_user, $_password);
if(!$this->resource)
throw new SqlException("Connection failed");
// Select database
if(!@mysql_select_db($_database, $this->resource))
throw new SqlException("Database selection failed");
// Set character encoding
$this->queryNoResponse("SET NAMES 'UTF8'");
}
public function query($_query) {
return new Query($_query, $this->resource);
}
}
Klasse Query
------------
class Query {
private $query = null;
public function __construct($_query, $_resource, $_buffered = true) {
//var_dump() gibt hier als zweite Zeile NULL aus!
// Do query
if($_buffered)
$this->query = @mysql_query($_query, $_resource);
else
$this->query = @mysql_unbuffered_query($_query, $_resource);
// Throw exception if query was not successful
if($this->query == null) throw new SqlException("Query failed", $_query);
}
public function fetch() {
if($this->query == null) throw new SqlException("Query not found");
if($row = mysql_fetch_array($this->query)) {
// Return row if new row fetched
return $row;
} else {
// Return false if no row left
return false;
}
}
}
Mein Script
-----------
$db = new Database("localhost", "root", "***", "test");
// Bis hierher noch kein Fehler, obwohl ja im Konstruktor auch schon ein Query ausgeführt wird
$query = $db->query("SELECT * FROM test"); // Hier tritt der Fehler auf
Noch eine Methode für die Klasse "Database", damit das Script funktioniert:
public function queryNoResponse($_query) {
if(!@mysql_query($_query, $this->resource))
throw new SqlException("Query failed", $_query);
}
Moin!
class Database {
private $resource = null;
Ganz simple Anmerkung, weil deine anfängliche Beschreibung schon darauf hindeutete, aber trotzdem hinreichend verwirrend war:
Wenn du PHP 5 nutzen kannst, dann nutze auch die mysqli-Funktionen, nicht die veralteten mysql-Funktionen.
Mysqli hat den nicht unbedeutenden Vorteil, dass du es direkt als Klasse nutzen kannst, oder sogar als Basisklasse mit neuen Funktionen erweitern.
Das dürfte dann dafür sorgen, dass deine gesamte jetzige Datenbankklasse überflüssig wird.
Außerdem: Das Realisieren eines singulären Datenbankzugangs wird üblicherweise über das Singleton-Pattern realisiert. Schon mal drüber nachgedacht? Dann hast du nämlich nicht eine Ressourcenvariable in multiplen Klasseninstanzen, sondern nur noch eine einzige Instanz.
Und als letzte Anmerkung: Exceptions werden von sehr vielen Leuten als extrem schlecht angesehen. Ich persönlich würde sie unbedingt vermeiden, wo immer es geht.
- Sven Rautenberg
Exceptions werden von sehr vielen Leuten als extrem schlecht angesehen. Ich persönlich würde sie unbedingt vermeiden, wo immer es geht.
Ui, du benutzt fehlercodes? da kannste ja direkt heimgehn, das ist längst nicht mehr stand der zeit. exceptions sind sehr viel praktischer, vor allem in verbindung mit klassen, da sie auch verschachtelte funktionsaufrufe verarbeiten können. und php5 ist ja inzwischen fast überall vorhanden.
Gruß,
Niklas
Hallo Niklas,
Exceptions werden von sehr vielen Leuten als extrem schlecht angesehen. Ich persönlich würde sie unbedingt vermeiden, wo immer es geht.
Ui, du benutzt fehlercodes? da kannste ja direkt heimgehn, das ist längst nicht mehr stand der zeit. exceptions sind sehr viel praktischer, vor allem in verbindung mit klassen, da sie auch verschachtelte funktionsaufrufe verarbeiten können.
Hier mal ein paar Links zum Thema, aber Vorsicht - vielleicht willst Du nach der Lektüre auch direkt heimgehen ;)
http://blogs.msdn.com/oldnewthing/archive/2005/01/14/352949.aspx
http://www.joelonsoftware.com/items/2003/10/13.html
http://www.joelonsoftware.com/articles/Wrong.html
Zumindest kann es ja nicht schaden sich die "andere Seite" mal anzuschauen.
Viele Grüße
Stefan
http://blogs.msdn.com/oldnewthing/archive/2005/01/14/352949.aspx
http://www.joelonsoftware.com/items/2003/10/13.html
http://www.joelonsoftware.com/articles/Wrong.html
ok ,ich seh ja ein, was ihr meint. 2 der seiten kenne ich auch schon. das haupt-gegenargument gegen exceptions ist dabei, dass es so schwer ist, guten exception-code zu schreiben. allerdings sind sie um einiges universeller und praktischer als error codes.
da ich mich für einen guten programmierer halte, benutze ich seit php5 exceptions und auch die meisten größeren php5-projekte (z.b. symfony) basieren auf exceptions. das liegt daran, dass es kaum szenarien gibt, die mit error-codes, aber nicht mit exceptions gelöst werden können.
ich nehme gerne die zusätzliche denk- und designarbeit in kauf, um flexibilität, skalierbarkeit und wiederverwertbarkeit zu vergrößern.
Gruß,
Niklas
Moin!
Exceptions werden von sehr vielen Leuten als extrem schlecht angesehen. Ich persönlich würde sie unbedingt vermeiden, wo immer es geht.
Ui, du benutzt fehlercodes? da kannste ja direkt heimgehn, das ist längst nicht mehr stand der zeit. exceptions sind sehr viel praktischer, vor allem in verbindung mit klassen, da sie auch verschachtelte funktionsaufrufe verarbeiten können. und php5 ist ja inzwischen fast überall vorhanden.
Siehst du in Matthias' Code irgendwo Exception-Handling? Ich nicht. Und sowas wäre doch bitter nötig, wenn man schon die traditionelle Fehlerbehandlung wegläßt, und sogar PHP-Fehlermeldungen durch @ unterdrückt.
Sicher, mit Exceptions kann man nette Dinge tun. Ich sehe hier aber keine netten Dinge, die getan werden, sondern nur von irgendwoher abgeschriebenen Krams.
- Sven Rautenberg
Siehst du in Matthias' Code irgendwo Exception-Handling? Ich nicht. Und sowas wäre doch bitter nötig, wenn man schon die traditionelle Fehlerbehandlung wegläßt, und sogar PHP-Fehlermeldungen durch @ unterdrückt.
die @ sind ja gerade dazu da, von den fehlercodes loszukommen. da er ja wohl keine spezifischeren fehlermeldungen braucht (ist wohl eher eine private page) braucht er auch keine differenzierte fehlerbehandlung.
abgefangen werden die eigenen exceptions natürlich nicht. das soll ja der user-code tun! mysql wirft ja keine exceptions, die man abfangen könnte.
Gruß,
Niklas
Moin!
Siehst du in Matthias' Code irgendwo Exception-Handling? Ich nicht. Und sowas wäre doch bitter nötig, wenn man schon die traditionelle Fehlerbehandlung wegläßt, und sogar PHP-Fehlermeldungen durch @ unterdrückt.
die @ sind ja gerade dazu da, von den fehlercodes loszukommen. da er ja wohl keine spezifischeren fehlermeldungen braucht (ist wohl eher eine private page) braucht er auch keine differenzierte fehlerbehandlung.
Wenn man keine differenzierte Fehlerbehandlung braucht, braucht man auch keine Exceptions. @ davorschreiben, und gut ist.
abgefangen werden die eigenen exceptions natürlich nicht. das soll ja der user-code tun! mysql wirft ja keine exceptions, die man abfangen könnte.
Von wem könnte der User-Code wohl kommen? Und ist es sinnvoll, in einer Query-Klasse eine DB-Klasse aufzurufen, die Exceptions werfen kann, darauf aber nicht zu reagieren?
Meine Klassen werfen keine Exceptions und geben immer sinnvolle Ergebnisse zurück, mit denen die aufrufende Stelle etwas anfangen kann - auch im Fehlerfall. Wenn die aufrufende Stelle interessiert, ob was schiefgegangen ist, kann sie den Fehler separat abfragen, sofern das notwendig erscheint. Konkret am Beispiel: Eine Query-Funktion liefert immer ein Array mit allen Ergebnissen. Das ist im Fall von "nix gefunden" und auch "DB unerreichbar" ein leeres Array, also ein sinnvoller Wert, den man problemlos einem foreach einspeisen kann, um alle Datensätze anzuzeigen. Wenn es wichtig ist, dass die Datenbank unerreichbar war, gibts dafür einen Funktionsaufruf mit der Fehlermeldung.
- Sven Rautenberg
hi Sven,
ich glaube nicht, dass diese Diskussion uns weiterbringt. Lass uns nicht mehr streiten ;P
Gruß,
Niklas
Anbei etwas größere Ausschnitte des Codes, viel mehr sollte dafür ja aber eigentlich nicht relevant sein
also ich kann hier keinen fehler erkennen, aber mir passiert sowas auch mal, dass man einfach auf dem schlauch steht. für mal an allen möglichen stellen ein echo "zeilennummer: "; print_r([aktuelle resourcenvariable]) ein. dann solltest du den bereich eingrenzen können, wo der wert NULL geht.
den kommentar
//var_dump() gibt hier als zweite Zeile NULL aus!
versteh ich ncith so ganz. warum gibt var_dump 2 zeilen aus? wie rufst du es denn auf?
BTW: Was Sven sagt, ist schon eine überlegung wert, nämlich eine zusätzliche singleton-klasse zu erstellen, die den datenbank-zugriff kapselt. dazu könntest du auch die aktuellen klasen behalten, nur noch eine neue dazu machen, z.b. DBConnection, die als singleton fungiert.
Gruß,
Niklas
So, habe den Fehler gefunden...
Habe die Funktion Database->query() irgendwo im System statisch aufgerufen, also
Database::query()
Kann mir mal jemand sagen, warum man Methoden, die nicht static sind, static aufrufen kann? Irgendwie erscheint mir das sehr verwirrend...
echo $begrüßung;
Kann mir mal jemand sagen, warum man Methoden, die nicht static sind, static aufrufen kann? Irgendwie erscheint mir das sehr verwirrend...
Das hat historische Gründe. Schalte im error_reporting das E_STRICT ein und du bekommt einen Hinweis auf die Verwendung von Code, der unter PHP4 üblich war, unter PHP5 aber nicht mehr verwendet werden soll.
echo "$verabschiedung $name";