YIMP - बूटस्ट्रैप 4 पर Yii 2 के लिए नियंत्रण कक्ष

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


नए संस्करण पर काम करते समय, मैंने इस विषय पर अपने सभी अनुभव को संक्षेप में प्रस्तुत करने का प्रयास किया, और इसके परिणामस्वरूप मुझे YIMP मिला - एक ऐसी बाइक जिसे मैं साझा करने में शर्मिंदा नहीं हूं : GitHub , LiveDemo , API प्रलेखन


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


तो, YIMP एक डैशबोर्ड है। यह एक तैयार व्यवस्थापक पैनल नहीं है, न कि सीएमएस या यहां तक ​​कि सीएमएफ भी। प्रतिनिधित्व कोड को स्वतंत्र रूप से लिखे जाने या Gii (टेम्पलेट संलग्न हैं) का उपयोग करने की आवश्यकता है। YIMP एक लेआउट प्रदान करता है जो परिभाषित करता है कि नियंत्रण कहाँ स्थित होना चाहिए, साथ ही साथ इंटरफ़ेस जिसके माध्यम से एप्लिकेशन डेटा को लेआउट में स्थानांतरित करता है। यह डेस्कटॉप पर कैसा दिखता है:



लेआउट अनुकूली। जैसे-जैसे स्क्रीन सिकुड़ती है, तत्व नेवबार में बटन के ऊपर से गायब या हिलने लगते हैं। नतीजतन , फोन पर एक ही पृष्ठ इस तरह दिखता है:


बेहतर है कि इसे स्पॉइलर के नीचे रखें

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


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


जैसा कि मैंने कहा, YIMP में एक इंटरफ़ेस शामिल है जिसके माध्यम से एप्लिकेशन लेआउट में डेटा स्थानांतरित करता है। आइए देखें कि यह कैसे होता है। हुड खोलो!


ख़ाका


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


कोड की 77 लाइनें। में तल्लीन करना आवश्यक नहीं है!
<?php use dmitrybtn\yimp\widgets\Alert; use dmitrybtn\yimp\Yimp; use yii\bootstrap4\Html; $yimp = new Yimp(); $yimp->register($this); /** @var string $content Content came from view */ ?> <?php $this->beginPage() ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="<?= Yii::$app->charset ?>"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <?php echo Html::csrfMetaTags() ?> <title><?php echo Html::encode($yimp->nav->getTitle()) ?></title> <?php $this->head() ?> </head> <body> <?php $this->beginBody() ?> <?php echo $yimp->navbar() ?> <?php echo $yimp->beginSidebars() ?> <?php echo $yimp->beginLeftSidebar() ?> <?php echo $yimp->beginLeftSidebarMenu() ?> <?php echo $yimp->menuLeft([ 'options' => ['class' => 'nav-pills flex-column border rounded py-2'] ]) ?> <?php echo $yimp->endLeftSidebarMenu() ?> <?php if (isset($this->blocks[$yimp::SIDEBAR_LEFT])): ?> <?php echo $this->blocks[$yimp::SIDEBAR_LEFT] ?> <?php endif ?> <?php echo $yimp->endLeftSidebar() ?> <?php echo $yimp->beginRightSidebar() ?> <?php echo $yimp->beginRightSidebarMenu() ?> <?php echo $yimp->menuRight([ 'options' => ['class' => 'nav-pills flex-column border rounded py-2'] ]) ?> <?php echo $yimp->endRightSidebarMenu() ?> <?php if (isset($this->blocks[$yimp::SIDEBAR_RIGHT])): ?> <?php echo $this->blocks[$yimp::SIDEBAR_RIGHT] ?> <?php endif ?> <?php echo $yimp->endRightSidebar() ?> <?php echo $yimp->endSidebars() ?> <?php echo $yimp->beginContent() ?> <?php echo $yimp->headerDesktop() ?> <?php echo Alert::widget() ?> <?php echo $content ?> <?php echo $yimp->endContent() ?> <?php if (isset($this->blocks[$yimp::FOOTER])): ?> <?php echo $this->blocks[$yimp::FOOTER] ?> <?php endif ?> <?php $this->endBody() ?> </body> </html> <?php $this->endPage() ?> 

जैसा कि आप देख सकते हैं, सभी YIMP मार्कअप विधियों में लिपटे हुए हैं। इन तरीकों में से अधिकांश बस उन लाइनों को प्रिंट करते हैं जो इस सरणी से ली गई हैं। हाँ, के सिद्धांत KISS - हमारे सभी।


कृपया ध्यान दें कि लेआउट में ब्लॉक का उपयोग किया जाता है। उन्हें विचारों में परिभाषित विगेट्स प्रदर्शित करने की आवश्यकता है (यह इस प्रकार है कि नियंत्रण कैसे प्रदान किए जाते हैं)। खैर, अगर विजेट को सभी पृष्ठों पर लटका देना चाहिए, तो इसे सीधे लेआउट में निर्धारित करना बेहतर होता है।


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


नियंत्रकों


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


अगला कदम नियंत्रकों में न केवल एक्शन हेडर को परिभाषित करने का निर्णय था, बल्कि ब्रेड क्रम्ब्स और मेनू भी थे। और ऐसा करो कि YIMP उन्हें पढ़ सके। और यहां हमें एक उदाहरण की आवश्यकता है। चलिए ProfileController वर्ग के एक संभावित कार्यान्वयन को देखते हैं।


सरल कोड की 52 लाइनें। ध्यान से देखने के लिए बेहतर है!
 class ProfileController extends \yii\web\Controller { public $nav; public function init() { parent::init(); $this->nav = new \dmitrybtn\yimp\Navigator; } public static function titleView() { return ' '; } public static function titlePassword() { return ' '; } public static function crumbsToView() { return [ ['label' => static::titleView(), 'url' => ['/profile/view']] ]; } public function actionView() { $this->nav->title = static::titleView(); $this->nav->menuRight = [ ['label' => ''], ['label' => static::titlePassword(), ['password']], ]; ... return $this->render('view'); } public function actionPassword() { $this->nav->title = static::titlePassword(); $this->nav->crumbs = static::crumbsToView(); ... return $this->render('password'); } } 

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


 ['label' => ProfileController::titleView(), 'url' => ['/profile/view']], 

बिलकुल विधियां क्यों? क्योंकि कल आपको वर्तमान उपयोगकर्ता के लॉगिन को प्रदर्शित करने के लिए "माई प्रोफाइल" शब्दों के बजाय पूछा जाएगा।


रोटी के टुकड़ों के साथ ही। मान लीजिए कि हमारे उपयोगकर्ता के पास चित्रों की एक सूची है, जिसके लिए ImageController जिम्मेदार है। फिर image/create आप लिख सकते image/create कार्रवाई image/create :


  $this->nav->crumbs = ProfileController::crumbsToView(), 

और रोटी के टुकड़ों को प्राप्त करें जैसे "होम / मेरी प्रोफ़ाइल / एक तस्वीर जोड़ें।" वैसे, चूंकि image/create क्रिया को "चित्र जोड़ें" कहा जाता है, profile/view क्रिया मेनू को ठीक करना होगा:


  $this->nav->menuRight = [ ['label' => ''], ['label' => static::titlePassword(), ['password']], ['label' => ImageController::titleCreate(), 'url' => ['/image/create']] ]; 

मुझे लगता है कि विचार समझ में आता है। मेरी राय में, यह एक सरल और प्रभावी उपाय है जिसके लिए आप एमवीसी प्रतिमान से दूर जा सकते हैं। हां, नियंत्रक कोड बड़ा हो रहा है, लेकिन नियंत्रक में इसके लिए एक जगह है - हम वहां व्यापार तर्क नहीं लिखते हैं, है ना? और हां, मुझे इस मामले पर आपकी राय जानने की बहुत दिलचस्पी होगी।


हम और आगे जा रहे हैं। जैसा कि आप अनुमान लगा सकते हैं, \dmitrybtn\yimp\Navigator संपत्ति, जिसे \dmitrybtn\yimp\Navigator रूप में परिभाषित किया गया है, हेडर, मेनू और ब्रेडक्रंब को नियंत्रक से लेआउट में स्थानांतरित करने के लिए उपयोग किया जाता है। और यह YIMP की एक और विशेषता है।



सेटिंग्स लेआउट में कैसे मिलती हैं? बहुत सरल है। इसके प्रारंभ के दौरान, YIMP वर्तमान नियंत्रक की नौसेना संपत्ति के लिए जाँच करता है। यदि यह संपत्ति पठनीय है और एक नेविगेटर ( instanceof \dmitrybtn\yimp\Navigator ) है, तो इसका उपयोग संबंधित जानकारी को प्रदर्शित करने के लिए किया जाता है। नेविगेटर में लेआउट तत्वों के अनुरूप गुण शामिल हैं, जिसकी एक पूरी सूची एपीआई प्रलेखन में देखना आसान है।


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


यह दृष्टिकोण YIMP और नियंत्रक के बीच सीधे संबंध को समाप्त करता है। सभी इंटरैक्शन को एक ऑब्जेक्ट के माध्यम से किया जाता है, जिसके कार्यान्वयन को डेवलपर द्वारा नियंत्रित किया जाता है। यही है, यह वही डिपेंडेंसी इनवर्जन प्रिंसिपल है जो SOLID से है या GRASP से लो कपलिंग है।


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


YIMP और नियंत्रक के बीच एक सीधा संबंध की अनुपस्थिति महत्वपूर्ण हो जाती है जब मॉड्यूल सिस्टम में दिखाई देते हैं जो YIMP के बारे में कुछ भी नहीं जानते हैं। या इसके विपरीत - वाईआईएमपी के तहत लिखे गए मॉड्यूल एक ऐसी प्रणाली में स्थापित किए जाते हैं जिसका उपयोग वाईआईएमपी नहीं करता है।


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


  'container' => [ 'definitions' => [ 'yimp-nav' => [ 'class' => '\your\own\Navigator', ] ] ], 

दूसरे मामले में, नियंत्रक में नाविक होगा, लेकिन इसे पढ़ने वाला कोई नहीं होगा। इस मामले में, मॉड्यूल में विचारों के लिए एक आवरण लिखने की सिफारिश की गई है, जो नेविगेटर को वर्तमान नियंत्रक से वाईआईआई में स्वीकार किए गए प्रारूप में अनुकूल करेगा। यही है, मुख्य क्षेत्र में <h1> <title> और ब्रेडक्रंब मापदंडों Yii::$app->view माध्यम से गुजरते Yii::$app->view , और बटन के रूप में सही मेनू प्रदर्शित करते हैं।


निष्कर्ष


YIMP अब एक संस्करण के बिना प्रकाशित हुआ है। मुझे पूर्व-रिलीज़ संस्करण प्रकाशित करने का कोई कारण नहीं दिखता - इसके लिए सब कुछ बहुत सरल है। मुझे लगता है कि वास्तविक परियोजना पर कुछ हफ़्ते का परीक्षण करना और तुरंत संस्करण 1.0.0 पर स्विच करना बेहतर है। इसलिए GitHub पर आलोचना, टिप्पणियों और मदद का बहुत स्वागत है।


और मैं एक मॉड्यूल को पूरा कर रहा हूं जो नियंत्रण को लागू करता है। कैसे खत्म करें - मैं लिखूंगा


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


सभी को धन्यवाद!

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


All Articles