डेटाबेस कनेक्शन के लिए ग्लोबल या सिंगलटन?


81

PHP में डेटाबेस कनेक्शन के लिए वैश्विक के बजाय सिंगलटन का उपयोग करने का क्या लाभ है? मुझे लगता है कि वैश्विक के बजाय सिंगलटन का उपयोग करना कोड को अनावश्यक रूप से जटिल बनाता है।

ग्लोबल के साथ कोड

$conn = new PDO(...);

function getSomething()
{
    global $conn;
    .
    .
    .
}

सिंगलटन के साथ कोड

class DB_Instance
{
    private static $db;

    public static function getDBO()
    {
        if (!self::$db)
            self::$db = new PDO(...);

        return self::$db;
    }
}

function getSomething()
{
    $conn = DB_Instance::getDBO();
    .
    .
    .
}

यदि वैश्विक या सिंगलटन के अलावा डेटाबेस कनेक्शन को इनिशियलाइज़ करने का एक बेहतर तरीका है, तो कृपया इसका उल्लेख करें और वैश्विक या सिंगलटन पर होने वाले फायदों का वर्णन करें।


यदि आप कस्टम सत्र संचालकों पर पीडीओ का उपयोग करने की योजना बना रहे हैं, तो आपको कुछ
ख़ासियतों के

जवाबों:


105

मुझे पता है कि यह पुराना है, लेकिन Dr8k का जवाब लगभग वहाँ था ।

जब आप कोड का एक टुकड़ा लिखने पर विचार कर रहे हों, तो मान लें कि यह बदलने वाला है। इसका मतलब यह नहीं है कि आप भविष्य में किसी बिंदु पर उस पर उस प्रकार के बदलावों को मान रहे हैं, जो उस पर फहराए गए होंगे, बल्कि यह कि कुछ परिवर्तन किया जाएगा।

इसे एक लक्ष्य बनाएं भविष्य में परिवर्तन करने के दर्द को कम करें: एक वैश्विक खतरनाक है क्योंकि एक ही स्थान पर प्रबंधन करना मुश्किल है। क्या होगा अगर मैं भविष्य में उस डेटाबेस कनेक्शन संदर्भ को जागरूक करना चाहता हूं? क्या होगा अगर मैं चाहता हूं कि इसे हर 5 वीं बार बंद और फिर से खोल दिया जाए। क्या होगा यदि मैं यह तय करूं कि अपने ऐप को स्केल करने के हित में मैं 10 कनेक्शनों के पूल का उपयोग करना चाहता हूं? या कनेक्शन की एक विन्यास संख्या?

एक सिंगलटन फैक्ट्री आपको वह लचीलापन देती है। मैंने इसे बहुत कम अतिरिक्त जटिलता के साथ स्थापित किया और एक ही कनेक्शन तक पहुंच से अधिक प्राप्त किया; मैं इस बात को बदलने की क्षमता हासिल करता हूं कि बाद में एक साधारण तरीके से मेरे लिए कैसे कनेक्शन को पारित किया गया।

ध्यान दें कि मैं केवल सिंगलटन के विपरीत सिंगलटन फैक्ट्री को कहता हूं । एक सिंगलटन और एक वैश्विक, सच के बीच बहुत कम अंतर है। और उसके कारण, एक सिंगलटन कनेक्शन होने का कोई कारण नहीं है: जब आप इसके बजाय एक नियमित वैश्विक बना सकते हैं तो आप उस समय को क्यों सेट करेंगे?

आपको कौन सी फैक्ट्री मिलती है, आपको कनेक्शन प्राप्त करने के लिए एक क्यों है, और यह तय करने के लिए कि आपको क्या कनेक्शन (या कनेक्शन) मिलना है।

उदाहरण

class ConnectionFactory
{
    private static $factory;
    private $db;

    public static function getFactory()
    {
        if (!self::$factory)
            self::$factory = new ConnectionFactory(...);
        return self::$factory;
    }

    public function getConnection() {
        if (!$this->db)
            $this->db = new PDO(...);
        return $this->db;
    }
}

function getSomething()
{
    $conn = ConnectionFactory::getFactory()->getConnection();
    .
    .
    .
}

फिर, 6 महीनों में जब आपका ऐप सुपर प्रसिद्ध है और डगिंग और स्लेशडॉट हो रहा है और आप तय करते हैं कि आपको एक से अधिक कनेक्शन की आवश्यकता है, तो आपको बस यह करना होगा कि गेटकनेक्शन () विधि में कुछ पूलिंग को लागू करें। या यदि आप तय करते हैं कि आप SQL लॉगिंग को लागू करने वाला रैपर चाहते हैं, तो आप PDO उपवर्ग पास कर सकते हैं। या यदि आप तय करते हैं कि आप हर आह्वान पर एक नया कनेक्शन चाहते हैं, तो आप ऐसा कर सकते हैं। यह कठोर होने के बजाय लचीली है।

कोड की 16 पंक्तियाँ, जिसमें ब्रेसिज़ भी शामिल हैं, जो आपको घंटों और घंटों और घंटों को बचाने के लिए लाइन से नीचे समान रूप से कुछ करने के लिए बचाएगी।

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


3
यकीन नहीं है, लेकिन मुझे लगता है कि आपका मतलब है: सार्वजनिक समारोह getConnection () {if ($! इस- db) $ यह-> db = नया PDO (...); $ यह लौटाओ-> db; }
Dycey

धन्यवाद! क्या मैं इस पद्धति का उपयोग return self::$factory->getConnection();करने के बजाय इसके उपयोग से कोई लाभ खो दूंगा return self::$factory;?
निको बर्न्स

3
मैं इस कोड का उपयोग उस परियोजना में करना चाहता हूं जो मैं कर रहा हूं। क्या मैं इस पृष्ठ का हवाला दे सकता हूं, और यदि हां, तो यह पाठ किस लाइसेंस के तहत है? क्या यह CC-BY, BSD या कुछ और है? मैंने वर्तमान में "अज्ञात - पब्लिक डोमेन पर विश्वास करें" के रूप में यह दावा किया है, लेकिन मैं इस पर सही लाइसेंस शर्तों को विशेषता देना चाहूंगा।
जॉनन्यूसिगयू

2
मुझे लगता है कि हमें getConnection () पद्धति में "$ db" "$ this-> db" बनाना चाहिए, अन्यथा "निजी $ db" वैरिएबल "का उपयोग नहीं किया जाता है", जिसे आधिकारिक तौर पर कहीं भी संदर्भित नहीं किया गया है।
डेवलपर १०

नमस्ते आपका समाधान शांत और स्केलेबल दिखता है। कृपया मुझे बताएं कि यहां क्या लागू करने की आवश्यकता है स्वयं :: $ फैक्टरी = नया कनेक्शनफैक्टरी (...);
आनंद

16

मुझे यकीन नहीं है कि मैं आपके विशिष्ट प्रश्न का उत्तर दे सकता हूं, लेकिन यह सुझाव देना चाहता हूं कि अगर यह वेब-आधारित प्रणाली के लिए है तो वैश्विक / सिंगलटन कनेक्शन ऑब्जेक्ट सबसे अच्छा विचार नहीं हो सकता है। DBMS आमतौर पर एक कुशल तरीके से बड़ी संख्या में अद्वितीय कनेक्शन का प्रबंधन करने के लिए डिज़ाइन किए जाते हैं। यदि आप एक वैश्विक कनेक्शन ऑब्जेक्ट का उपयोग कर रहे हैं, तो आप कुछ चीजें कर रहे हैं:

  1. आपको सभी डेटाबेस कनेक्शनों को क्रमिक रूप से करने के लिए पृष्ठों को मजबूर करना और एसिंक्रोनस पेज लोड पर किसी भी प्रयास को मारना है।

  2. डेटाबेस तत्वों पर खुले ताले को आवश्यक रूप से अधिक से अधिक पकड़ना, समग्र डेटाबेस प्रदर्शन को धीमा करना।

  3. आपके डेटाबेस के कुल कनेक्शनों की अधिकतम संख्या को अधिकतम करना और नए उपयोगकर्ताओं को संसाधनों तक पहुँचने से रोक सकता है।

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

[संपादित करें]

बड़े आकार की परिस्थितियों में, हर बार जब आप डेटास को हिट करते हैं तो नए कनेक्शन बना सकते हैं। हालांकि, उत्तर वैश्विक संबंध बनाने और हर चीज के लिए इसका पुन: उपयोग करने के लिए नहीं है। जवाब कनेक्शन पूलिंग है।

कनेक्शन पूलिंग के साथ, कई अलग-अलग कनेक्शन बनाए रखे जाते हैं। जब अनुप्रयोग द्वारा कनेक्शन की आवश्यकता होती है, तो पूल से पहला उपलब्ध कनेक्शन पुनः प्राप्त कर लिया जाता है और फिर एक बार इसका काम पूरा हो जाने के बाद इसे पूल में लौटा दिया जाता है। यदि एक कनेक्शन का अनुरोध किया जाता है और कोई भी उपलब्ध नहीं है, तो दो चीजों में से एक होगा: क) यदि अनुमत कनेक्शन की अधिकतम संख्या तक नहीं पहुंचा जाता है, तो एक नया कनेक्शन खोला जाता है, या बी) एप्लिकेशन को कनेक्शन उपलब्ध होने का इंतजार करने के लिए मजबूर किया जाता है। ।

नोट: .Net भाषाओं में, कनेक्शन पूलिंग को डिफ़ॉल्ट रूप से ADO.Net ऑब्जेक्ट्स द्वारा नियंत्रित किया जाता है (कनेक्शन स्ट्रिंग सभी आवश्यक जानकारी सेट करता है)।

इस पर टिप्पणी करने के लिए क्रैड का धन्यवाद।


मुझे लगता है कि सिंगलटन का उपयोग करने से मुझे कनेक्शन को देर से शुरू करने का लाभ मिलता है, जबकि अगर मैं वैश्विक उपयोग करता हूं, तो मैं संभवतः स्क्रिप्ट की शुरुआत में लगभग आरंभ कर दूंगा। क्या मैं सही हूँ?
इमरान

सही है, अगर आप इस सड़क से नीचे जाना चाहते हैं तो सिंगलटन उस लाभ को प्रदान करेगा।
Dr8k

असल में, यह सब बड़े पैमाने पर निर्भर करता है। बड़े पैमाने पर वेब परिनियोजन में, बड़े पैमाने पर DB कनेक्शन खराब हैं। यही कारण है कि PostgreSQL और Java के लिए pgBouncer जैसे ऐप संसाधन पूलिंग करते हैं।
गेविन एम। रॉय

यह सच है, लेकिन मुझे लगता है कि उचित कनेक्शन पूलिंग केवल वैश्विक अभिमुखी वस्तुओं का उपयोग करने के लिए अलग है। कनेक्शन पूलिंग अभी भी कई कनेक्शनों का उपयोग करता है, यह सिर्फ अधिकतम संख्या को सीमित करता है और उन्हें ओवरहेड सेटअप ओवरहेड करने के लिए समय पर फिर से मना करता है।
Dr8k

5
ध्यान दें कि PHP के मामले में "वैश्विक" PHP पृष्ठों में परिवर्तनशील वैश्विक नहीं है। इसका मतलब सिर्फ इतना है कि इसे फंक्शन्स से एक्सेस किया जा सकता है।
फरवरी को एटल गोरल

7

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

इसलिए, मैं वैश्विक और सिंगलटन को अनदेखा कर दूंगा क्योंकि दोनों वास्तव में ओओपी नहीं हैं।

आप जो देख रहे थे वह निर्भरता इंजेक्शन है

आप पर निर्भरता इंजेक्शन (उदाहरण के साथ) से संबंधित PHP आधारित जानकारी को पढ़ने के लिए http://compords.symfony-project.org/d dependency-injection/ trunk / book / 01-D dependency-Injection पर आसानी से देख सकते हैं।


3

दोनों ही पैटर्न एक ही शुद्ध प्रभाव प्राप्त करते हैं, आपके डेटाबेस कॉल के लिए एक एकल एक्सेस प्वाइंट प्रदान करते हैं।

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

एक अन्य मामूली अंतर यह है कि वैश्विक कार्यान्वयन अन्य चर नामों को आवेदन में अनायास ही रौंद सकता है। यह संभावना नहीं है कि आप कभी गलती से एक और वैश्विक $ db संदर्भ की घोषणा करेंगे, हालांकि यह संभव है कि आप इसे गलती से अधिलेखित कर सकते हैं (कहते हैं, आप लिखते हैं अगर ($ db = null) जब आप लिखने का मतलब था ($ db == null)। सिंगलटन ऑब्जेक्ट को रोकता है।


2

यदि आप एक निरंतर कनेक्शन का उपयोग नहीं करने जा रहे हैं, और ऐसा नहीं करने के मामले हैं, तो मुझे ओओ डिजाइन में एक वैश्विक की तुलना में वैचारिक रूप से अधिक तालमेल वाला एक सिंगलटन लगता है।

एक सच्चे OO आर्किटेक्चर में, एक सिंगलटन हर बार ऑब्जेक्ट को एक नया उदाहरण बनाने से ज्यादा प्रभावी होता है।


2

दिए गए उदाहरण पर, मुझे सिंगलेट्स का उपयोग करने का कोई कारण नहीं दिखता है। अंगूठे के एक नियम के रूप में अगर मेरी एकमात्र चिंता किसी वस्तु के एक उदाहरण की अनुमति देना है, अगर भाषा इसकी अनुमति देती है, तो मैं ग्लोबल्स का उपयोग करना पसंद करता हूं


1

सामान्य तौर पर मैं एक डेटाबेस कनेक्शन के लिए एक सिंगलटन का उपयोग करता हूं ... आप डेटाबेस से बातचीत करने के लिए हर बार एक नया कनेक्शन नहीं बनाना चाहते हैं ... यह आपके नेटवर्क के पूर्णता और बैंडविड्थ को चोट पहुंचा सकता है ... क्यों एक बनाएँ नया एक, जब एक उपलब्ध है ... बस मेरे 2 सेंट ...

RWendi


वैश्विक स्कोप में कनेक्शन को इनिशियलाइज़ करने के साथ, मैं प्रति पृष्ठ एक बार कनेक्शन को इनिशियलाइज़ कर रहा हूँ, और फ़ंक्शंस में उस ग्लोबल वैरिएबल का उपयोग कर रहा हूँ, जिसे डेटाबेस के साथ इंटरैक्ट करने की आवश्यकता है।
इमरान

डेटाबेस कनेक्शन के लिए सिंगलटन का उपयोग करना डीबीएमएस के साथ प्रत्येक इंटरैक्शन पर कनेक्शन को फिर से बनाने के समान नहीं है। एक सिंगलटन सिर्फ इतना है; किसी दिए गए वर्ग का एक उदाहरण, और केवल एक ही विश्व स्तर पर मौजूद है। आपको एक ही बार में विभिन्न डेटाबेस से जुड़ने की आवश्यकता हो सकती है।
रोब

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

0

यह काफी सरल है। ग्लोबल या सिंगलटन का उपयोग कभी न करें।


4
जब यह सिंगलटन पैटर्न की बात आती है, तो हमेशा कहते हैं कि कभी नहीं
1800 जानकारी 1

3
यदि आप एक से अधिक लॉग प्रदाता चाहते हैं तो क्या होगा? कौन कहता है कि मैं एक फ़ाइल, और कंसोल में प्रवेश नहीं कर सकता हूं?
1800 जानकारी 1

2
तो आप फिर एक विरोधी पैटर्न (सिंगलटन) को दूसरे (ईश्वर वस्तु) के साथ जोड़ देंगे
1800 सूचना

3
हाँ। और इसलिए वैश्विक वर्ग की वस्तुओं की अनुमति देकर, हर प्रमुख ओओपी भाषा के डिजाइनर करते हैं। यदि आप एक एकेश्वरवादी हैं और आप ईश्वर का प्रतिनिधित्व करने के लिए एक वस्तु चाहते हैं, तो आप जो देख रहे हैं वह एक सिंगलटन ईश्वर वस्तु है। और कुछ भी गलत है।
स्टीव जेसप

4
अगर मैं एक नश्वरवादी था और मैं एक ईश्वर वस्तु बनाना चाहता था, तो मैं अपने गॉड ऑब्जेक्ट को बनाने के लिए एक मोनोथेस्टीब्रेटीफैक्टरी पैटर्न का उपयोग करने का उल्लेख कर सकता हूं? यह बहुपत्नी उपयोगकर्ताओं के लिए प्रतिबोध्यता को खोल देता है ताकि एक PolytheistAbstractfactory निर्दिष्ट करके मेरे कार्यक्रम का उपयोग कर सकें।
1800 सूचना

0

सलाह के रूप में सिंगलटन और ग्लोबल दोनों मान्य हैं और एक ही सिस्टम, प्रोजेक्ट, प्लगइन, उत्पाद, आदि के भीतर शामिल हो सकते हैं ... मेरे मामले में, मैं वेब (प्लगइन) के लिए डिजिटल उत्पाद बनाता हूं।

मैं मुख्य वर्ग में केवल सिंगलटन का उपयोग करता हूं और मैं सिद्धांत रूप से इसका उपयोग करता हूं। मैं लगभग इसका उपयोग नहीं करता हूं क्योंकि मुझे पता है कि मुख्य वर्ग इसे फिर से नहीं करेगा

<?php // file0.php

final class Main_Class
{
    private static $instance;
    private $time;

    private final function __construct()
    {
        $this->time = 0;
    }
    public final static function getInstance() : self
    {
        if (self::$instance instanceof self) {
            return self::$instance;
        }

        return self::$instance = new self();
    }
    public final function __clone()
    {
        throw new LogicException("Cloning timer is prohibited");
    }
    public final function __sleep()
    {
        throw new LogicException("Serializing timer is prohibited");
    }
    public final function __wakeup()
    {
        throw new LogicException("UnSerializing timer is prohibited");
    }
}

लगभग सभी माध्यमिक वर्गों के लिए वैश्विक उपयोग, उदाहरण:

<?php // file1.php
global $YUZO;
$YUZO = new YUZO; // YUZO is name class

रनटाइम के दौरान मैं उपयोग कर सकता हूं एक ही उदाहरण में उनके तरीकों और विशेषताओं को कॉल करने के ग्लोबल का क्योंकि मुझे अपने मुख्य उत्पाद वर्ग के किसी अन्य उदाहरण की आवश्यकता नहीं है।

<?php // file2.php
global $YUZO;
$YUZO->method1()->run();
$YUZO->method2( 'parameter' )->html()->print();

मुझे लगता है कि वैश्विक के साथ उत्पाद का काम करने में सक्षम होने के लिए एक ही उदाहरण का उपयोग करना है क्योंकि मुझे एक ही वर्ग के उदाहरणों के लिए एक कारखाने की आवश्यकता नहीं है, आमतौर पर उदाहरण का कारखाना बड़ी प्रणालियों के लिए या बहुत दुर्लभ उद्देश्यों के लिए है।

In conclusion:, यदि आप पहले से ही अच्छी तरह से समझते हैं कि विरोधी पैटर्न सिंगलटन है और ग्लोबल को समझते हैं , तो आप 2 विकल्पों में से एक का उपयोग कर सकते हैं या उन्हें मिला सकते हैं लेकिन अगर मैं दुरुपयोग करने की सलाह नहीं देता हूं क्योंकि कई प्रोग्रामर हैं जो बहुत अपवाद और वफादार हैं प्रोग्रामिंग OOP, इसे मुख्य और माध्यमिक कक्षाओं के लिए उपयोग करें जिसे आप निष्पादन समय के भीतर बहुत उपयोग करते हैं। (यह आपको बहुत सी सीपीयू बचाता है)। 😉

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.