क्योंकि आपका Model
क्लास एक नया Database
को इंस्टेंट करता है इसके कंस्ट्रक्टर में ऑब्जेक्ट, हर बार जब आप एक Model
. को इंस्टेंट करते हैं (या इसे विस्तारित करने वाला कोई भी वर्ग), आप प्रभावी रूप से एक नया . खोल रहे हैं डेटाबेस कनेक्शन। अगर आप कई Model
बनाते हैं ऑब्जेक्ट्स, प्रत्येक का अपना स्वतंत्र डेटाबेस कनेक्शन होता है, जो असामान्य है, आमतौर पर अनावश्यक है, संसाधनों का अच्छा उपयोग नहीं है, बल्कि सक्रिय रूप से हानिकारक भी है क्योंकि इसने सर्वर के सभी उपलब्ध कनेक्शनों का उपयोग किया है।
उदाहरण के लिए, Model
. की एक सरणी बनाने के लिए लूपिंग ऑब्जेक्ट:
// 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)
डिपेंडेंसी इंजेक्शन का इस्तेमाल करें:
समाधान निर्भरता इंजेक्शन का उपयोग करना है और पास Database
Model::__construct()
में ऑब्जेक्ट करें इसके बजाय इसे स्वयं को तत्काल करने की अनुमति दें।
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;
}
}
इसका उपयोग करने के लिए, नियंत्रण कोड (कोड जो आपके मॉडल को तुरंत चालू करेगा) को स्वयं new Database()
कॉल करना चाहिए केवल एकबार। नियंत्रक कोड द्वारा बनाई गई उस वस्तु को तब सभी मॉडलों के निर्माणकर्ताओं को पास किया जाना चाहिए।
// Instantiate one Database
$db = new Database();
// Pass it to models
$model = new Model($db);
उपयोग के मामले के लिए जहां आपको वास्तव में एक मॉडल के लिए एक अलग स्वतंत्र डेटाबेस कनेक्शन की आवश्यकता होती है, आप इसे एक अलग सौंप सकते हैं। विशेष रूप से, यह उपयोगी है परीक्षण के लिए . आप एक परीक्षण डेटाबेस वस्तु, या एक नकली वस्तु को प्रतिस्थापित कर सकते हैं।
// Instantiate one Database
$db = new Database();
$another_db = new Database();
// Pass it to models
$model = new Model($db);
$another_model = new Model($another_db);
लगातार कनेक्शन:
जैसा कि टिप्पणियों में उल्लेख किया गया है, लगातार कनेक्शन का उपयोग करना संभवतः एक समाधान है, लेकिन वह समाधान नहीं जिसकी मैं अनुशंसा करता हूं . पीडीओ एक मौजूदा कनेक्शन को उसी क्रेडेंशियल के साथ पुन:उपयोग करने का प्रयास करेगा (जैसा कि आपके सभी के पास होगा), लेकिन आप जरूरी नहीं चाहते कि कनेक्शन को स्क्रिप्ट निष्पादन में कैश किया जाए। यदि आपने इसे इस तरह करने का निर्णय लिया है, तो आपको विशेषता को Database
. में पास करना होगा कंस्ट्रक्टर।
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'");
}
प्रासंगिक दस्तावेज यहां है:http://php.net/manual /hi/pdo.connections.php#example-950
सिंगलटन समाधान:
सिंगलटन पैटर्न (यह भी अनुशंसित नहीं) का उपयोग करके, आप कम से कम इसे मॉडल कोड में खोज/प्रतिस्थापन में कम कर सकते हैं। Database
वर्ग को अपने लिए कनेक्शन रखने के लिए एक स्थिर संपत्ति की आवश्यकता होती है। मॉडल तब Database::getInstance()
. पर कॉल करते हैं new Database()
. के बजाय कनेक्शन पुनः प्राप्त करने के लिए। आपको Database::getInstance()
स्थानापन्न करने के लिए मॉडल कोड में एक खोज और प्रतिस्थापन करने की आवश्यकता होगी ।
हालांकि यह अच्छी तरह से काम करता है और इसे लागू करना मुश्किल नहीं है, आपके मामले में यह परीक्षण को थोड़ा और कठिन बना देगा क्योंकि आपको पूरे Database
को बदलना होगा। एक ही नाम के परीक्षण वर्ग के साथ वर्ग। उदाहरण के आधार पर आप किसी टेस्ट क्लास को इंस्टेंस के आधार पर आसानी से प्रतिस्थापित नहीं कर सकते।
Database
. पर सिंगलटन पैटर्न लागू करें :
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;
}
}
अब आपको केवल Model
को बदलना होगा उपयोग करने के लिए कोड Database::getInstance()
:
class Model {
protected $_db;
public function __construct(){
// Retrieve the database singleton
$this->_db = Database::getInstance();
}
}