2012-03-27 17 views
0

In PHP, ich folgende Singleton Database Klasse habe:PHP Singleton Datenbankabfrage

class Database 
{ 
    private static $instance; 

    private function __construct() 
    { 
     self::$instance = new mysqli('localhost', 'root', 'Matthias', 'financecontrol', '3307'); 
     if (!self::$instance) { 
      throw new Exception('Could not connect to database in function __construct.'); 
     } 
    } 

    public static function getInstance() 
    { 
     if (!self::$instance) { 
      self::$instance = new Database(); 
     } 
     return self::$instance; 
    } 

} 

Jedes Mal, wenn ich versuche, eine Abfrage auf der Datenbank in einer anderen PHP-Datei auszuführen, zum Beispiel, ob ein Benutzer zu überprüfen, ist bereits vorhanden:

function userExists($username) 
    { 
     try { 
      $connection = Database::getInstance(); 

      $result = $connection->query("select * from user where username='$username'"); 
      if (!$result) { 
       throw new Exception("Connection to database failed in function userExists."); 
      } 
      if ($result->num_rows > 0) { 
       return true; 
      } else { 
       return false; 
      } 
     } catch (Exception $ex) { 
      $errorPager = new ErrorpageGenerator(); 
      $errorPager->generateErrorPage($ex->getMessage()); 
      return false; 
     } 
    } 

ich erhalte eine Fehlermeldung "PHP Fatal error: Call to undefined Methode Datenbank :: query() in User.php auf der Leitung 44"

ich habe versucht, eine Abfrage-Funktion in der DATABAS Hinzufügen Die Klasse, aber das schien das Problem nicht zu beheben. Irgendwelche Ideen? Danke

Antwort

2

Sie müssen diese Methode natürlich hinzufügen. Aber Sie können nicht zuordnen Datenbank() und das MySQLi Objekt m_pInstance

so tun:

class Database 
{ 
    private static $conn; 

    // ... 
    public function __construct() 
    { 
    self::$conn = new mysqli('localhost', 'root', 'root', 'database', '3307'); 
    //... 

und dann

public function query($sql) 
{ 
    return self::$conn->query($sql); 
    // or 
    return mysqli_query(self::$conn, $sql); 
} 

EDIT

Arbeitscode:

class Database 
{ 
    private static $instance = null; 

    private static $conn; 

    private function __construct() 
    { 
    self::$conn = new mysqli('localhost', 'root', 'root', 'database', '3307'); 
    } 

    public static function getInstance() 
    { 
    if (self::$instance == null) { 
     self::$instance = new Database(); 
    } 

    return self::$instance; 
    } 

    public function query($sql) 
    { 
    return self::$conn->query($sql); 
    } 
} 
+0

ich so etwas versucht haben. Aber das erzeugt diesen Fehler: "Parent: Child-Prozess wurde mit Status 255 beendet - Neustart." Und die Webseite stürzt einfach ab. – Matthias

+0

Hm vielleicht mit 'self :: $ conn-> query ($ sql)'? (Ich hatte es zuerst statische) –

+0

Ja, ich habe diesen Fehler bemerkt und es selbst behoben. Gleiches Ergebnis. – Matthias

0

Ihr Code sieht nicht richtig aus.

Zuerst weisen Sie $ m_pInstance eine neue Datenbankinstanz zu. Aber dann weisen Sie ihm im Konstruktor eine neue mysqli-Instanz zu. Ich bin mir nicht sicher, wie PHP diesen Fall behandelt, aber es scheint, dass es es als Datenbank-Objekt behandelt, wie von Ihrer Fehlermeldung angezeigt. Die Datenbankklasse hat jedoch keine Abfragemethode.

Also wäre die Lösung, das mysqli-Objekt in einem anderen Feld zu speichern und Getter und Setter dafür hinzuzufügen oder die Methoden zu delegieren.

1

Sie erhalten diesen Fehler, da Database::$m_pInstance eine Instanz von Database Klasse und nicht Instanz von MySQLi enthält. Sie haben einen „Konflikt“ zwischen zu Teilen des Codes erstellt:

public static function getInstance() 
{ 
    if (!self::$m_pInstance) { 
     self::$m_pInstance = new Database(); // << PROBLEM 
    } 

    return self::$m_pInstance; 
} 

Welche überschreibt, was Ihr Konstruktor tut:

private function __construct() 
{ 
    self::$m_pInstance = new mysqli(/* .. */); // PROBLEM 
    if (!self::$m_pInstance) { 
     throw new Exception('Could not .. blah'); 
    } 
    else { 
     return self::$m_pInstance; 
    } 
} 

Auch wenn der Konstruktor ordnet self::$m_pInstance die Instanz von MySQLi Objekt, wird es überschrieben von self::$instance = new Database(); direkt nach.

Auch in php __constuct() Methode sollte nicht return, jemals.

Das heißt, denke ich, sollten Sie warnen, dass Singleton ist betrachtet ein Anti-Muster, zu sein und sollte vermieden werden. Ihr Code hat auch den unbeabsichtigten Nebeneffekt, der Sie zwingt, nur eine Datenbank (keine Verbindung, die Datenbank) pro Anwendung verfügbar zu haben.

Sie können aus der Beobachtung wenige Vorträge profitieren:

+0

+1 Ich muss zustimmen, nach "Dependency Injection" suchen, es ist ein so viel besserer Ansatz! –