2010-05-15 7 views
22

मैं एकल से वैश्विक या बेहतर से बेहतर सिंगलटन के बारे में कोई चर्चा नहीं करना चाहता हूं। मैंने एसओ पर समान विषयों के बारे में दर्जनों प्रश्न पढ़े, लेकिन मैं इस विशिष्ट प्रश्न के उत्तर के साथ नहीं आया, इसलिए मुझे आशा है कि कोई इस सवाल का जवाब देकर मुझे (या अधिक) वास्तविक सरल उदाहरण, और सैद्धांतिक चर्चाओं के साथ जवाब दे सकता है।PHP - एक डीबी अबास्ट्रक्शन परत स्थैतिक वर्ग बनाम सिंगलटन ऑब्जेक्ट का उपयोग करती है?

मेरे ऐप में मैं और कोड mysql_connect/mysql_select_db/mysql...

मैं कक्षा लिख ​​सकता है में हर जगह लिखने के बिना डीबी पर कार्य करने के लिए सार डीबी परत को ठेठ डीबी वर्ग या तो एक स्थिर वर्ग के रूप में:

class DB 
{ 
    private static $connection = FALSE; //connection to be opened 

    //DB connection values 
    private static $server = NULL; private static $usr = NULL; private static $psw = NULL; private static $name = NULL; 

    public static function init($db_server, $db_usr, $db_psw, $db_name) 
    { 
     //simply stores connections values, without opening connection 
    } 

    public static function query($query_string) 
    { 
     //performs query over alerady opened connection, if not open, it opens connection 1st 
    } 

    ... 
} 

या एक सिंगलटन के रूप में:

class DBSingleton 
{ 
    private $inst = NULL; 
    private $connection = FALSE; //connection to be opened 

    //DB connection values 
    private $server = NULL; private $usr = NULL; private $psw = NULL; private $name = NULL; 

    public static function getInstance($db_server, $db_usr, $db_psw, $db_name) 
    { 
     //simply stores connections values, without opening connection 

     if($inst === NULL) 
     $this->inst = new DBSingleton(); 
     return $this->inst; 
    } 
    private __construct()... 

    public function query($query_string) 
    { 
     //performs query over already opened connection, if connection is not open, it opens connection 1st 
    } 

    ... 
} 

तब मेरे एप्लिकेशन में के बाद अगर मैं डीबी क्वेरी करना चाहते हैं मैं

//Performing query using static DB object 
DB:init(HOST, USR, PSW, DB_NAME); 
DB::query("SELECT..."); 

//Performing query using DB singleton 
$temp = DBSingleton::getInstance(HOST, USR, PSW, DB_NAME); 
$temp->query("SELECT..."); 

मेरे लिए सिंगलटन केवल लाभ static के रूप में वर्ग के प्रत्येक विधि की घोषणा से बचने के लिए मिल गया है कर सकता है। मुझे यकीन है कि आप में से कुछ EXAMPLE को विशिष्ट मामले में सिंगलटन के वास्तविक लाभ के लिए दे सकते हैं। अग्रिम में धन्यवाद।

+1

जो कोई भी मतदान किया एक टिप्पणी छोड़ और कृपया समझाएं सकता है। –

+2

डेटाबेस क्लास को सिंगलटन बनाने या स्थिर वर्ग के रूप में व्यवहार करने की बिल्कुल आवश्यकता नहीं है। मेरा मतलब है कि यह किस उद्देश्य से सेवा करता है? यदि आप एक ऐसा एप्लिकेशन बनाना चाहते हैं जो एक साथ दो अलग-अलग डेटाबेस कनेक्शन की आवश्यकता है, तो आप मूल रूप से पहले ही खराब हो गए हैं। और आलसी प्रारंभिक (वास्तविक कनेक्शन का) एक वर्ग के साथ पूरी तरह से संभव है जो कई उदाहरणों की अनुमति देता है। –

+0

@fireeyedboy: आपके लिए धन्यवाद टिप्पणी लेकिन मैं वास्तव में आपके बिंदु को समझ नहीं पा रहा हूं। अंत में आपको लगता है कि यह एक सिंगलटन या स्थैतिक वर्ग बेहतर है और क्यों? –

उत्तर

7

क्या निम्नलिखित (सरलीकृत) उदाहरण के साथ गलत है:

class Database 
{ 
    protected $_connection; 

    protected $_config; 

    public function __construct(array $config) // or other means of passing config vars 
    { 
     $this->_config = $config; 
    } 

    public function query($query) 
    { 
     // use lazy loading getter 
     return $this->_getConnection()->query($query); 
    } 

    protected function _getConnection() 
    { 
     // lazy load connection 
     if($this->_connection === null) 
     { 
      $dsn = /* create valid dsn string from $this->_config */; 

      try 
      { 
       $this->_connection = new PDO($dsn, $this->_config[ 'username' ], $this->_config[ 'password' ]); 
      } 
      catch(PDOException $e) 
      { 
       /* handle failed connecting */ 
      } 
     } 

     return $this->_connection; 
    } 
} 

$db1 = new Database(array(
    'driver' => 'mysql', 
    'host'  => 'localhost', 
    'dbname' => 'test', 
    'username' => 'test_root', 
    'password' => '**********' 
)); 

$db2 = new Database(array(
    'driver' => 'pgsql', 
    'host'  => '213.222.1.43', 
    'dbname' => 'otherdb', 
    'username' => 'otherdb_root', 
    'password' => '**********' 
)); 

$someModel  = new SomeModel($db1); 
$someOtherModel = new SomeOtherModel($db2); 
$yetAnotherModel = new YetAnotherModel($db2); 

यह दर्शाता है कि कैसे आप आलसी लोड हो रहा है कनेक्शन का उपयोग कर सकते हैं, और अभी भी विभिन्न डेटाबेस कनेक्शन का उपयोग करने के विकल्प होता है।

डेटाबेस उदाहरण केवल उनके व्यक्तिगत कनेक्शन से कनेक्ट होंगे जब कोई ऑब्जेक्ट जो किसी एक उदाहरण का उपभोग करता है (इस मामले में मॉडल में से एक) उदाहरण की विधि को कॉल करने का निर्णय लेता है।

+0

क्षमा करें, लेकिन मैं आपके उदाहरण को कम नहीं करता हूं। 1) यह सिंगलटन नहीं है, बल्कि एक जेनरिक क्लास है, इसलिए यह स्पष्ट है कि आप अलग-अलग डीबी के लिए कई आबादी बना सकते हैं, जो एक सामान्य वर्ग है, इसके विपरीत एक सिंग्लियन आपको हमेशा उसी वस्तु को वापस करने के लिए है कनेक्शन। 2) जब आप "यह उदाहरण" कहते हैं, तब भी स्थैतिक वर्ग और सिंगलटन केवल आवश्यक होने पर कॉनेटिक्स करता है, इनिट फ्यूशन केवल डीबी कनेक्शन पैरामीटर को रोकता है, कनेक्शन केवल तभी किया जाता है जब क्वेरी फ़ंक्शन पर कॉल की आवश्यकता होती है (टिप्पणियां पढ़ें मेरा प्रश्न कोड)। –

+1

मार्को, कारण मैं एक सिंगलटन का उपयोग करने के खिलाफ सलाह देता हूं क्योंकि, जब आपके एप्लिकेशन (या भविष्य के आवेदन) को एक ही समय में दो अलग-अलग डेटाबेस कनेक्शन की आवश्यकता होती है, तो आप उस वर्ग का अब और उपयोग नहीं कर सकते हैं, क्योंकि यह केवल एक कनेक्शन के लिए समायोजित कर सकता है । इसके अलावा मुझे लगता है कि आप इस सिंगलटन का उपयोग आसानी से कहीं भी पसंद से प्राप्त करने के लिए करते हैं, है ना? लेकिन यह मजबूत युग्मन बनाता है। हालांकि, जब आप उपभोग करने वाले ऑब्जेक्ट के कन्स्ट्रक्टर को डेटाबेस कनेक्शन पास करते हैं, जैसा कि मेरे उदाहरण में, आप ढीले युग्मन बनाते हैं, ताकि आप इसे उसी इंटरफेस के साथ आसानी से दूसरे वर्ग के लिए स्वैप कर सकें। –

+0

ओह मुझे समझ में नहीं आया कि आप वास्तव में सिंगलटन या स्थैतिक वर्ग का उपयोग न करने का सुझाव दे रहे थे, लेकिन सामान्य वर्ग का उपयोग करने के लिए। अब मैं तुम्हारा मुद्दा समझ गया। –

4

मेरी सबसे हाल की परियोजना में, मैं वास्तव में डेटाबेस वर्ग को पूरी तरह स्थैतिक बनाकर "अच्छे" डिजाइन सिद्धांतों के खिलाफ चला गया। इसका कारण यह है कि मैंने PHP ऑब्जेक्ट्स पर बहुत सी कैशिंग का उपयोग किया। मूल रूप से मैंने डेटाबेस को एक निर्भरता इंजेक्शन के रूप में प्रत्येक ऑब्जेक्ट के निर्माता के माध्यम से पारित किया था, हालांकि मैं यह सुनिश्चित करना चाहता था कि डेटाबेस को पूरी तरह से आवश्यक होने तक कनेक्ट नहीं करना पड़े। इस प्रकार, उस ऑब्जेक्ट के सदस्य चर के रूप में डेटाबेस का उपयोग करना व्यावहारिक नहीं होता क्योंकि यदि आप किसी ऑब्जेक्ट को कैश से अनियंत्रित करते हैं, तो आप डेटाबेस से कनेक्ट नहीं करना चाहेंगे जबतक कि आपने वास्तव में कोई ऑपरेशन नहीं किया।

तो अंत में मेरे पास केवल दो (सार्वजनिक) स्थिर कार्य थे, डाटाबेस :: fetch() और डेटाबेस :: execute() जो जांच करेगा कि यह पहले से कनेक्ट हो चुका है या नहीं, और यदि नहीं, तो यह कनेक्ट होगा और क्वेरी करें। इस तरह मुझे deserialization के बारे में चिंता करने की ज़रूरत नहीं होगी और शायद ही कभी संभव के रूप में कनेक्ट होगा। यह तकनीकी रूप से इकाई परीक्षण असंभव बनाता है।

आपको हमेशा हर एक अच्छे अभ्यास का पालन नहीं करना पड़ता है। लेकिन मैं अभी भी ऐसा करने के खिलाफ सिफारिश करता हूं जो मैंने किया था क्योंकि कुछ इसे समयपूर्व अनुकूलन मानेंगे।

+0

मैं कहूंगा कि एक सिंगलटन बनाना समयपूर्व अनुकूलन है, क्योंकि स्थैतिक वर्ग को सीरेट करना बहुत आसान है। –

3

मेरी सलाह: सिंगलटन और स्थिर सभी का उपयोग करके रोकें।

क्यों?क्योंकि आप उन निर्भरताओं को सम्मिलित करेंगे जो आपके कोड को अन्य परियोजनाओं में अनुपयोगी प्रदान करेंगे, और यूनिट परीक्षण करने की अनुमति नहीं देंगे। सिंगलटन का उपयोग करते हुए ढीले युग्मन के बारे में भी भूल जाओ।

विकल्प? निर्भरता अन्तःक्षेपण। के बाद से यह वैश्विक है, हर जगह का उपयोग करने के आकर्षक,

$db = DBSingleton::blabla(); // everytime I need ya

लेकिन यह भी: http://www.potstuck.com/2009/01/08/php-dependency-injection

+0

PHP निर्भरताओं से बचने के लिए स्थैतिक वर्गों से बचें, लेकिन फिर मुझे हर जगह वैश्विक उपयोग करने की आवश्यकता है: http://stackoverflow.com/questions/10486107/php-do-not-use-static-classes-to-avoid- निर्भरता-but- तो-i-need-to-use-glob –

+0

साइड-तथ्य: यह लगभग 2015 है और यहां तक ​​कि सबसे बड़ी ढांचे और मूल रूप से सभी ओआरएम libs स्थिर विधियों का उपयोग करते हैं। – Sliq

1

डीबी पुस्तकालय स्थिर बनाना, निश्चित रूप से छोटे और तेज है कर रही है।

तो, अन्य तरीकों चुनें यदि आप स्वच्छ कोड चाहते ... और स्थिर चुनें यदि आप जरूरत त्वरित कोड ;-)

-1
/* Data base*/ 
class Database 
{ 
    /* Database field definition */ 
    private static $_instance; /instance 
    private $_connection; 
    private $DB_USER = "database_user_name_here"; 
    private $DB_PASS = "your_password_here"; 
    private $DB_NAME = "your_database_name_here"; 
    private $DB_SERVER = "localhost"; 

    /* Initiate the database connection */ 
    private function __construct() 
    { 
     $this->_connection = new mysqli($this->DB_SERVER , 
             $this->DB_USER , 
             $this->DB_PASS , 
             $this->DB_NAME); 
     /* Test if connection succeeded */ 
     if (mysqli_connect_errno()) { 
      die("Database connection failed: " . 
       mysqli_connect_error() . 
       " (" . mysqli_connect_errno() . ")" 
      ); 
     } 
    } 

    /** 
    * Instance of the database 
    * @return Database 
    * 
    */ 
    public static function Instance() 
    { 
     if (!self::$_instance) { // If no instance then make one 
      self::$_instance = new self(); 
     } 

     return self::$_instance; 
    } 

    /** 
    * Void duplicate connection 
    */ 
    private function __clone() { } 

    /* Return a connection */ 
    public function getConnection() 
    { 
     return $this->_connection; 
    } 

} 

/** This is how you would use it in a different class. 
    @var TYPE_NAME $connection */ 
$db = Database::Instance(); 
$connection = $db->getConnection(); 
संबंधित मुद्दे