Weil Ihr Model
Klasse instanziiert eine neue Database
-Objekt in seinem Konstruktor jedes Mal, wenn Sie ein Model
instanziieren (oder jede Klasse, die es erweitert), öffnen Sie tatsächlich ein neues Datenbankverbindung. Wenn Sie mehrere Model
erstellen Objekte, hat dann jedes seine eigene unabhängige Datenbankverbindung, was ungewöhnlich, normalerweise unnötig, keine gute Nutzung von Ressourcen, aber auch aktiv schädlich ist, da es alle verfügbaren Verbindungen des Servers verbraucht hat.
Beispielsweise eine Schleife zum Erstellen eines Arrays von Model
Objekte:
// If a loop creates an array of Model objects
while ($row = $something->fetch()) {
$models[] = new Model();
}
// each object in $models has an independent database connection
// the number of connections now in use by MySQL is now == count($models)
Verwenden Sie Abhängigkeitsinjektion:
Die Lösung besteht darin, Abhängigkeitsinjektion und pass zu verwenden die Database
Objekt in das Model::__construct()
anstatt ihm zu erlauben, sich selbst zu instanziieren.
class Model {
protected $_db;
// Accept Database as a parameter
public function __construct(Database $db) {
// Assign the property, do not instantiate a new Database object
$this->_db = $db;
}
}
Um es dann zu verwenden, sollte der steuernde Code (der Code, der Ihre Modelle instanziiert) selbst new Database()
aufrufen nur einmal. Dieses vom steuernden Code erstellte Objekt muss dann an die Konstruktoren aller Modelle weitergegeben werden.
// Instantiate one Database
$db = new Database();
// Pass it to models
$model = new Model($db);
Für den Anwendungsfall, dass Sie tatsächlich eine andere unabhängige Datenbankverbindung für ein Modell benötigen, können Sie ihm eine andere geben. Dies ist insbesondere zum Testen nützlich . Sie können ein Testdatenbankobjekt oder ein Scheinobjekt ersetzen.
// Instantiate one Database
$db = new Database();
$another_db = new Database();
// Pass it to models
$model = new Model($db);
$another_model = new Model($another_db);
Permanente Verbindungen:
Wie in den Kommentaren erwähnt, ist die Verwendung einer dauerhaften Verbindung möglicherweise eine Lösung, aber nicht die Lösung, die ich empfehlen würde . PDO versucht, eine vorhandene Verbindung mit denselben Anmeldeinformationen wiederzuverwenden (wie alle Ihre), aber Sie möchten nicht unbedingt, dass die Verbindung über die Skriptausführung hinweg zwischengespeichert wird. Wenn Sie sich dafür entschieden haben, müssen Sie das Attribut an die Database
übergeben Konstruktor.
try {
// Set ATTR_PERSISTENT in the constructor:
parent::__construct(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME,DB_USER,DB_PASS, array(PDO::ATTR_PERSISTENT => true));
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
}
Die entsprechende Dokumentation finden Sie hier:http://php.net/manual /en/pdo.connections.php#example-950
Singleton-Lösung:
Mit einem Singleton-Pattern (ebenfalls nicht empfohlen) könnten Sie dies zumindest auf ein Suchen/Ersetzen im Modellcode reduzieren. Die Database
Die Klasse benötigt eine statische Eigenschaft, um eine Verbindung für sich selbst aufrechtzuerhalten. Modelle rufen dann Database::getInstance()
auf statt new Database()
um die Verbindung abzurufen. Sie müssten im Modellcode suchen und ersetzen, um Database::getInstance()
zu ersetzen .
Obwohl es gut funktioniert und nicht schwer zu implementieren ist, würde es in Ihrem Fall das Testen etwas erschweren, da Sie die gesamte Database
ersetzen müssten Klasse mit einer gleichnamigen Testklasse. Sie können eine Testklasse nicht einfach von Instanz zu Instanz ersetzen.
Singleton-Muster auf Database
anwenden :
class Database extends PDO{
// Private $connection property, static
private static $connection;
// Normally a singleton would necessitate a private constructor
// but you can't make this private while the PDO
// base class exposes it as public
public function __construct(){
try {
parent::__construct(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME,DB_USER,DB_PASS);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
} catch(PDOException $e){
Logger::newMessage($e);
logger::customErrorMsg();
}
}
// public getInstance() returns existing or creates new connection
public static function getInstance() {
// Create the connection if not already created
if (self::$connection == null) {
self::$connection = new self();
}
// And return a reference to that connection
return self::$connection;
}
}
Jetzt müssten Sie nur noch das Model
ändern Code zur Verwendung von Database::getInstance()
:
class Model {
protected $_db;
public function __construct(){
// Retrieve the database singleton
$this->_db = Database::getInstance();
}
}