Symfony2 निर्भरता इंजेक्शन अनुभागीय दृश्य

लेख से आप यह पता लगा सकते हैं कि Symfony2 एप्लिकेशन कैसे शुरू होता है और काम करता है। मैं इस आधुनिक ढांचे के बारे में लेखों की श्रृंखला को जारी रखना चाहूंगा और डिपेंडेंसी इंजेक्शन (डीआई - डिपेंडेंसी इंजेक्शन) जैसे सर्विस कंपोनेंट के रूप में भी ध्यान देना चाहूंगा।

प्रस्तावना


सबसे पहले, मैं Symfony2 की वास्तुकला का संक्षेप में वर्णन करना चाहूंगा। अनुप्रयोग के मूल में घटक (घटक) होते हैं, जो एक दूसरे तत्वों से स्वतंत्र होते हैं और कुछ कार्य करते हैं। एप्लिकेशन का व्यावसायिक तर्क तथाकथित है बंदा । सिम्फनी 2 के अंतर्निहित घटकों के साथ, आप तीसरे पक्ष के विक्रेताओं के किसी भी अन्य पुस्तकालय घटक (लोकप्रिय ज़ेंड सहित) को ऑटोलैडर में सही ढंग से पंजीकृत करने के लिए भूलकर भी कनेक्ट कर सकते हैं। एक नियम के रूप में, सिम्फनी 2 के मूल के साथ, ऐसे घटक जैसे कि टिग (टेम्पलेट इंजन), डॉक्ट्रीन 2 (ओआरएम), स्विफ्टमेलर (मेलर) की आपूर्ति की जाती है।

सेवा उन्मुख वास्तुकला


स्वतंत्र सेवाओं के रूप में बाहर काम करने वाले मॉड्यूल में कार्यों को विभाजित करने की विचारधारा को आमतौर पर सेवा-उन्मुख वास्तुकला (SOA) कहा जाता है। यह Symfony2 की नींव है।

निर्भरता इंजेक्शन और नियंत्रण का उलटा


ओओपी का उपयोग करते हुए एक एप्लिकेशन में, डेवलपर वस्तुओं के साथ काम करता है और काम करता है। प्रत्येक वस्तु का उद्देश्य कुछ कार्यों (सेवा) को पूरा करना है और यह संभव है कि अन्य वस्तुएं उसके अंदर समाविष्ट हो जाएं। यह पता चला है कि एक वस्तु दूसरे पर निर्भर करती है, जिसके परिणामस्वरूप मूल वस्तु को वंशज उदाहरणों की स्थिति को नियंत्रित करना होगा। डिपेंडेंसी इंजेक्शन (DI) पैटर्न को इस आवश्यकता को खत्म करने और बाहरी कोड के लिए निर्भरता प्रबंधन प्रदान करने के लिए डिज़ाइन किया गया है। यानी एक वस्तु हमेशा किसी अन्य वस्तु (अवरोही) के तैयार उदाहरण के साथ काम करेगी और यह नहीं जान पाएगी कि यह वस्तु कैसे बनी है, किसके द्वारा और किस पर निर्भरताएं मौजूद हैं। एक मूल वस्तु बस एक आश्रित वस्तु को प्रतिस्थापित करने के लिए एक तंत्र प्रदान करती है, आमतौर पर एक निर्माता या सेटर विधि के माध्यम से। नियंत्रण के इस हस्तांतरण को नियंत्रण का व्युत्क्रम कहा जाता है। उलटा यह है कि वस्तु अब अपने वंशज वस्तुओं की स्थिति को नियंत्रित नहीं करती है।
Symfony2 में निर्भरता इंजेक्शन घटक कंटेनर पर निर्भर करता है, सभी पंजीकृत सेवाओं का प्रबंधन करता है और उनके बीच संबंधों की निगरानी करता है, सेवा उदाहरण बनाता है, और लुकअप तंत्र का उपयोग करता है।

IoC कंटेनर


DI घटक को सेवा वस्तुओं के बीच निर्भरता और इसे प्रबंधित करने वाली सेवाओं को जानने की आवश्यकता है। ऐसा करने के लिए, Symfony2 में एक कंटेनरबर्ल है, जो एक बंडल में xml मानचित्र या प्रत्यक्ष निर्भरता गठन के आधार पर बनता है। यह सिम्फनी 2 में कैसे होता है। मान लीजिए कि एप्लिकेशन में App \ HelloBundle है। एक कंटेनर बनाने के लिए और इसे अपनी सेवाओं के साथ पूरक करने के लिए (फ्रेमवर्क स्तर पर कंटेनर पहले से मौजूद है और मानक बंडलों में परिभाषित सेवाओं से भरा हुआ है), आपको बंडल रूट निर्देशिका में DependencyInjection निर्देशिका बनाने और \ Symfony \ Component \ HttpKernel \ DependencyInjection \ विस्तार वर्ग के लोड विधि को फिर से परिभाषित करने की आवश्यकता है (तदनुसार) Symfony2 नियमों को वर्ग AppHelloBundleExtension, यानी, [नाम स्थान] [बंडल नाम] एक्सटेंशन) को कॉल करना चाहिए।

# App\HelloBundle\DependencyInjection\AppHelloBundleExtension.php <?php namespace App\HelloBundle\DependencyInjection; use Symfony\Component\HttpKernel\DependencyInjection\Extension; class AppHelloBundleExtension extends Extension { public function load(array $configs, ContainerBuilder $container) { ... } } 


अनुप्रयोग सेवाएँ


आपके पास पहले से ही AppHelloBundleExtension होने के बाद, आप अपनी सेवाओं को जोड़ना शुरू कर सकते हैं। यह ध्यान दिया जाना चाहिए कि इस मामले में आप स्वयं सेवा वस्तुओं के साथ काम नहीं कर रहे हैं, लेकिन केवल उनकी परिभाषा (परिभाषा) के साथ। क्योंकि इस संदर्भ में कंटेनर अभी भी गायब है, यह केवल परिभाषाओं के आधार पर बनता है।
 # App\HelloBundle\DependencyInjection\AppHelloBundleExtension.php public function load(array $configs, ContainerBuilder $container) { $definition = new Definition('HelloBundle\\SomePrettyService'); $container->addDefinition($definition); } 

ऐसी "मैनुअल" कोड पीढ़ी के अलावा, आप एक xml सेवा मानचित्र के आयात का उपयोग कर सकते हैं, जो कुछ नियमों के अनुसार बनाया गया है। जाहिर है, यह अधिक सुविधाजनक और अधिक दृश्य है।
 # App\HelloBundle\DependencyInjection\AppHelloBundleExtension.php public function load(array $configs, ContainerBuilder $container) { $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('services.xml'); } 

हालांकि, कुछ भी हमें परिभाषा बनाने के दोनों तरीकों का उपयोग करने से रोकता है।
 # App\HelloBundle\DependencyInjection\AppHelloBundleExtension.php public function load(array $configs, ContainerBuilder $container) { $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('services.xml'); $definition = $container->getDefinition('some.pretty.service'); // ... // do something with $definition // ... } 

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

अब देखते हैं कि xml में भविष्य की सेवा परिभाषा कैसे बनाई जाए। फ़ाइल में निम्नलिखित मूल संरचना है

< container xmlns ="http://symfony.com/schema/dic/services" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://symfony.com/schema/dic/services symfony.com/schema/dic/services/services-1.0.xsd" >
< parameters >
< parameter > ... </ parameter >
...
</ parameters >
< services >
< service > ... </ service >
...
</ services >
</ container >


* This source code was highlighted with Source Code Highlighter .

प्रत्येक सेवा परिभाषा को सेवा टैग द्वारा परिभाषित किया गया है। इसके लिए निम्नलिखित विशेषताएँ दी गई हैं।

पैरामीटर विशेषताएँ

निम्नलिखित तत्वों को सेवा टैग के अंदर नेस्ट किया जा सकता है।
< argument />
< tag />
< call />


* This source code was highlighted with Source Code Highlighter .

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

< parameters >
< parameter key ="some_service.class" > App\HelloBundle\Service </ parameter >
</ parameters >
< services >
< service id ="some_service" class ="%some_service.class%" />
</ services >


* This source code was highlighted with Source Code Highlighter .

इस मामले में सभी मापदंडों को एक ही स्थान पर सूचीबद्ध करना सुविधाजनक है, और फिर सेवा परिभाषाओं में उन्हें एक से अधिक बार उपयोग करना है।

सेवा परिभाषा उदाहरण


अब अधिक स्पष्ट रूप से ऊपर वर्णित उदाहरणों द्वारा दर्शाया जा सकता है:
< service id ="some_service_name" class ="App\HelloBundle\Service\Class" >
< argument > some_text </ argument >
< argument type ="service" id ="reference_service" /><! -- -- >
< argument type ="collection" >
< argument key ="key" > value </ argument >
</ argument >
< call method ="setRequest" >
< argument type ="service" id ="request" />
</ call >
</ service >


* This source code was highlighted with Source Code Highlighter .

ऊपर वर्णित कंटेनर सेवा, जब यह पहली बार एक्सेस की जाती है, तो निम्न में बदल जाती है
 //     $referenceService = ... ; $request = ... ; $service = new App\HelloBundle\Service\Class('some_text', $referenceService, array('key' => 'value')); $service->setRequest($request); 

एक ही बात है, लेकिन Symfony2 परिभाषाओं में
 # App\HelloBundle\DependencyInjection\AppHelloBundleExtension.php public function load(array $configs, ContainerBuilder $container) { $definition = new Definition('App\HelloBundle\Service\Class'); $definition->addArgument('some_text'); $definition->addArgument(new Reference('reference_service')); $definition->addArgument(array('key' => 'value')); $definition->addMethodCall('setRequest', array(new Reference('request'))); $container->setDefinition('some_service_name', $definition); } 

आप इस सेवा को प्राप्त कर सकते हैं, उदाहरण के लिए, इस तरह एमवीसी नियंत्रक में
 $this->container->get('some_service_name'); 

मुझे लगता है कि सिम्फनी 2 कर्नेल के साथ आपूर्ति की जाने वाली मानक बंडलों में सेवा परिभाषाएं बनाने के और अधिक उदाहरण मिल सकते हैं।

निष्कर्ष


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

संबंधित लिंक


मार्टिन फावलर: कंट्रोल कंटेनर का उलटा और डिपेंडेंसी इंजेक्शन पैटर्न
निर्भरता इंजेक्शन
नियंत्रण उलटा (नियंत्रण उलटा)
Symfony2 - सेवा कंटेनर

Source: https://habr.com/ru/post/In117572/


All Articles