दिलचस्प पोस्ट
कैसे HTTPS के साथ काम करने के लिए file_get_contents () प्राप्त करें? नियमित अभिव्यक्ति में क्या विशेष पात्रों को बचाना चाहिए? जुड़ने और पंक्ति-आधारित सीमित (पेजिंग) के साथ सीतनिद्रा में विशिष्ट परिणाम कैसे प्राप्त करें? एसडी कार्ड + एंड्रॉइड में संग्रहीत छवि का उरी / पथ थंबनेल प्राप्त करें जब मैं चुप मोड में ऑडियो चला रहा हूं और IOS 6 में लॉक करता हूं? ग्रुप द्वारा गठबंधन / एक कॉलम को संरेखित करें मैं सरल पीपी कार्यों में "निर्भरता इंजेक्शन" का उपयोग कैसे कर सकता हूं, और मुझे परेशान करना चाहिए? दो अंकों (अक्षांश, देशांतर) के बीच की दूरी की गणना करना कैसे एक JQuery चयनकर्ता से एक DOM तत्व प्राप्त करने के लिए दूरस्थ यूआरएल से कनेक्ट करना जिसके लिए जावा का इस्तेमाल करने के लिए प्रमाणीकरण की आवश्यकता होती है प्रक्रिया चल रहा है, जबकि लगातार उपप्रकाशन आउटपुट प्रिंट करें संमिश्र प्राथमिक कुंजी और व्याख्या के साथ अनेक कई मैपिंग मानचित्रण: सेमीके के लिए नया जीसीसी पथ कैसे निर्दिष्ट करें जावा में विरासत – उप-वर्ग का उद्देश्य बनाने से सुपरक्लास के निर्माता भी आमंत्रित करता है क्यों बिल्कुल? क्रॉस-डोमेन कुकीज

कक्षा में वैश्विक चर का उपयोग करें

मैं एक पेजगिन क्लास बनाने की कोशिश कर रहा हूं और कक्षा के बाहर एक वैरिएबल का उपयोग कर रहा हूं।

लेकिन यह मुझे एक गैर-ऑब्जेक्ट पर "सदस्य फ़ंक्शन क्वेरी (कॉल) को कॉल करने वाला घातक त्रुटि दे रहा है"।

यह सूचकांक फ़ाइल है:

$db = new DB_MySQL("localhost", "root", "", "test"); // connect to the database include_once("pagi.php"); $pagination = new pagi(); $records = $pagination->get_records("SELECT * FROM `table`"); 

और यह pagi.php फ़ाइल है:

 class pagi { public function get_records($q) { $x = $db->query($q); return $db->fetch($x); } } 

क्या क्लास के अंदर वर्ग के बाहर की ओर से इस चर का इस्तेमाल करना संभव है, कक्षा के अंदर एक नया निर्माण किए बिना?

वेब के समाधान से एकत्रित समाधान "कक्षा में वैश्विक चर का उपयोग करें"

इसे हल करने का सही तरीका अन्य वस्तु ( निर्भरता इंजेक्शन ) में डेटाबेस ऑब्जेक्ट को इंजेक्ट करना होगा:

 $db = new DB_MySQL("localhost", "root", "", "test"); // connect to the database include_once("pagi.php"); $pagination = new Paginator($db); $records = $pagination->get_records("SELECT the, fields, you, want, to retrieve FROM `table`"); class Paginator { protected $db; // Might be better to use some generic db interface as typehint when available public function __construct(DB_MySQL $db) { $this->db = $db; } public function get_records($q) { $x = $this->db->query($q); return $this->db->fetch($x); } } 

एक और तरीका है जिसे आप इसे हल कर सकते हैं डेटाबेस क्लास का उदाहरण उस पद्धति में शामिल करके जो इसका उपयोग करता है:

 $db = new DB_MySQL("localhost", "root", "", "test"); // connect to the database include_once("pagi.php"); $pagination = new Paginator(); $records = $pagination->get_records("SELECT the, fields, you, want, to retrieve FROM `table`", $db); class Paginator { public function get_records($q, DB_MySQL $db) { $x = $db->query($q); return $db->fetch($x); } } 

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

यह भी ध्यान रखें कि मैंने अपने वर्ग का नाम बदलकर Paginator को Paginator । Paginator वर्ग के लिए एक बेहतर नाम IMHO है क्योंकि यह अन्य लोगों (पुनः) को आपके कोड को देखने के लिए स्पष्ट है। यह भी ध्यान रखें कि मैंने सबसे पहले अक्षर अपरकेस बना दिया है।

मैंने एक और चीज को "वाइल्डकार्ड" * का उपयोग करने के बजाय उपयोग किए जा रहे फ़ील्ड चुनने के लिए क्वेरी को बदल दिया है। इसी कारण से मैंने क्लासनाम बदल दिया है: अपना कोड देखने वाले लोगों को पता होगा कि डाटाबेस और / या परिणाम की जाँच किए बिना फ़ॉल्स क्या पुनर्प्राप्त किए जाएंगे।

अद्यतन करें

चूंकि जवाब ने चर्चा की कि मैं ऑब्जेक्ट global को घोषित करने के बजाय निर्भरता इंजेक्शन मार्ग क्यों जाना चाहूंगा, मैं स्पष्ट करता हूं कि मैं global खोजशब्द पर निर्भरता इंजेक्शन का उपयोग क्यों करूंगा: जब आपके पास एक विधि होती है:

 function get_records($q) { global $db; $x = $db->query($q); return $db->fetch($x); } 

जब आप उपरोक्त विधि का उपयोग कर रहे हैं, तो यह स्पष्ट नहीं है कि कक्षा या विधि का उपयोग $db पर निर्भर करता है। इसलिए यह एक गुप्त निर्भरता है इसके बाद के संस्करण खराब होने का एक अन्य कारण यह है कि आपने उस पद्धति / कक्षा में $db उदाहरण (इस प्रकार DB_MySQL ) वर्ग को कसकर जोड़ा है। क्या होगा अगर आपको कुछ बिंदुओं पर 2 डाटाबेस का उपयोग करने की आवश्यकता है अब आपको global $db को global $db2 बदलने के लिए सभी कोड के माध्यम से जाना होगा। किसी अन्य डेटाबेस पर स्विच करने के लिए आपको अपना कोड बदलने की आवश्यकता नहीं होनी चाहिए इस कारण से, आपको ऐसा नहीं करना चाहिए:

 function get_records($q) { $db = new DB_MySQL("localhost", "root", "", "test"); $x = $db->query($q); return $db->fetch($x); } 

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

कुछ लोगों को लगता है कि सिंगलटन पैटर्न एक डेटाबेस ऑब्जेक्ट तक पहुंच प्राप्त करने का सही तरीका है, लेकिन यह स्पष्ट होना चाहिए, उपर्युक्त सभी को पढ़ना, एक सिंगलटन मूलतः चीजों को global बनाने का एक और तरीका है। यह अलग दिख सकता है, लेकिन इसकी सटीक विशेषताओं और इसलिए global रूप से एक जैसी समस्याएं हैं।

हालांकि मैं मानता हूं कि डेटाबेस के लिए निर्भरता मॉडल अच्छा है, मैं व्यक्तिगत रूप से एक स्थिर कनेक्शन का उपयोग करता हूं जो डेटाबेस वर्ग के सभी उदाहरणों के लिए उपलब्ध होता है और जब भी मुझे एक की आवश्यकता होती है, क्वेरी करने के लिए उदाहरण बनाते हैं यहाँ एक उदाहरण है:

 <?php //define a database class class DB { //the static connection. //This is available to all instances of the class as the same connection. private static $_conn; //store the result available to all methods private $result; //store the last query available to all methods private $lastQuery; //static connection function. connects to the database and stores that connection statically. public static function connect($host, $user, $pass, $db){ self::$_conn = mysqli_connect($host, $user, $pass, $db); } //standard function for doing queries. uses the static connnection property. public function query($query){ $this->lastQuery = $query; $this->result = mysqli_query(self::$_conn, $query); //process result, return expected output. } } //create connection to the database, this connection will be used in all instances of DB class DB::connect('local', 'DB_USER', 'DB_PASS'); //create instance to query $test = new DB; //do query $test->query("SELECT * FROM TABLE"); //test function function foo(){ //create instance to use in this function $bar = new DB; //do query $bar->query("SELECT * FROM OTHER_TABLE"); //return results return $bar->fetchArray(); } 

इस तरह से मैं किसी भी समारोह, विधि … आदि के भीतर डीबी के सभी आवेशों को बना सकता हूं और मेरे सभी प्रश्नों को करने के लिए क्लास के स्थानीय उदाहरण का उपयोग कर सकता हूं। सभी उदाहरण उसी कनेक्शन का उपयोग करते हैं

एक बात ध्यान देने की बात है कि यह केवल प्रति परिभाषित वर्ग के डेटाबेस के लिए एक कनेक्शन की अनुमति देता है, लेकिन मैं केवल एक का उपयोग करता हूं इसलिए यह मेरे लिए कोई समस्या नहीं है

आप get_records विधि के कॉल में डीबी-कनेक्शन ( $db ) जोड़ सकते हैं:

यहां केवल कोड की प्रासंगिक पंक्तियां हैं:

पहली फ़ाइल:

 $records = $pagination->get_records("SELECT * FROM `table`", $db); 

दूसरी फाइल:

 public function get_records($q, $db) { 

अन्य जवाब इस प्रकार अब तक एक वैश्विक उपयोग करने के लिए निश्चित रूप से बेहतर हैं क्योंकि इससे आपके एनकॅप्सुलेशन को नष्ट हो जाएगा (जैसे आपको उस ऑब्जेक्ट को उस विधि को कॉल करने से पहले परिभाषित करना होगा)।

विधि हस्ताक्षर में लागू करने के लिए या किसी वर्ग का उपयोग नहीं करना बेहतर है।

सिंगलटन पैटर्न का उपयोग करें और एक स्थैतिक उदाहरण के साथ डीबीआईआईएसक्यूएल को इंजेक्ट करें!