मेरे कहने का कारण यह है कि लेन-देन मॉडल परत में नहीं होते हैं, मूल रूप से यह है:
मॉडल अन्य मॉडलों में विधियों को कॉल कर सकते हैं।
यदि कोई मॉडल लेन-देन शुरू करने का प्रयास करता है, लेकिन उसे इस बात का कोई ज्ञान नहीं है कि उसके कॉलर ने पहले ही लेन-देन शुरू कर दिया है, तो मॉडल को सशर्त करना होगा लेन-देन शुरू करें, जैसा कि @Bubba's answer में कोड उदाहरण में दिखाया गया है। . मॉडल के तरीकों में एक ध्वज को स्वीकार करना होता है ताकि कॉलर यह बता सके कि उसे अपना लेनदेन शुरू करने की अनुमति है या नहीं। या फिर मॉडल में अपने कॉलर की "लेन-देन में" स्थिति को क्वेरी करने की क्षमता होनी चाहिए।
public function setPrivacy($privacy, $caller){
if (! $caller->isInTransaction() ) $this->beginTransaction();
$this->privacy = $privacy;
// ...action code..
if (! $caller->isInTransaction() ) $this->commit();
}
क्या होगा यदि कॉलर कोई वस्तु नहीं है? PHP में, यह एक स्थिर विधि या केवल गैर-वस्तु-उन्मुख कोड हो सकता है। यह बहुत गन्दा हो जाता है, और मॉडल में बहुत सारे बार-बार कोड की ओर जाता है।
यह कंट्रोल कपलिंग का एक उदाहरण भी है। , जिसे बुरा माना जाता है क्योंकि कॉलर को बुलाए गए ऑब्जेक्ट के आंतरिक कामकाज के बारे में कुछ पता होना चाहिए। उदाहरण के लिए, कुछ आपके मॉडल की विधियों में $transactional पैरामीटर हो सकता है, लेकिन अन्य विधियों में वह पैरामीटर नहीं हो सकता है। कॉल करने वाले को कैसे पता चलेगा कि पैरामीटर कब मायने रखता है?
// I need to override method's attempt to commit
$video->setPrivacy($privacy, false);
// But I have no idea if this method might attempt to commit
$video->setFormat($format);
दूसरा समाधान जो मैंने देखा है (या प्रोपेल जैसे कुछ ढांचे में भी लागू किया गया है) beginTransaction()
बनाना है और commit()
नो-ऑप्स जब डीबीएएल जानता है कि यह पहले से ही लेनदेन में है। लेकिन यह विसंगतियों को जन्म दे सकता है यदि आपका मॉडल प्रतिबद्ध करने का प्रयास करता है और पाता है कि यह वास्तव में प्रतिबद्ध नहीं है। या रोलबैक करने का प्रयास करता है और उस अनुरोध को अनदेखा कर दिया गया है। मैंने इन विसंगतियों के बारे में पहले भी लिखा है।
मैंने जो समझौता किया है, वह यह है कि मॉडल लेनदेन के बारे में नहीं जानते हैं . मॉडल को पता नहीं है कि उसका अनुरोध setPrivacy()
. के लिए है या नहीं ऐसा कुछ है जो इसे तुरंत करना चाहिए या यह एक बड़ी तस्वीर का हिस्सा है, परिवर्तनों की एक अधिक जटिल श्रृंखला जिसमें कई मॉडल शामिल हैं और केवल चाहिए प्रतिबद्ध रहें यदि ये सभी परिवर्तन सफल होते हैं। यही लेन-देन का बिंदु है।
इसलिए यदि मॉडल्स को यह नहीं पता कि वे अपना लेन-देन शुरू कर सकते हैं या करना चाहिए, तो कौन करता है? GRASP में एक नियंत्रक पैटर्न शामिल है। जो एक उपयोग के मामले के लिए एक गैर-यूआई वर्ग है, और इसे उस उपयोग के मामले को पूरा करने के लिए सभी टुकड़ों को बनाने और नियंत्रित करने की जिम्मेदारी सौंपी गई है। नियंत्रक लेनदेन के बारे में जानते हैं क्योंकि यही वह जगह है जहां इस बारे में सभी जानकारी उपलब्ध है कि क्या पूरा उपयोग मामला जटिल है, और मॉडल में एक लेनदेन (या शायद कई लेनदेन के भीतर) में कई बदलाव किए जाने की आवश्यकता है।
मैंने पहले जो उदाहरण लिखा है, वह यह है कि beforeAction()
. में लेन-देन शुरू करना है एक MVC नियंत्रक की विधि और इसे afterAction()
. में प्रतिबद्ध करें विधि, एक सरलीकरण . है . नियंत्रक को वर्तमान कार्रवाई को पूरा करने के लिए तार्किक रूप से आवश्यक कई लेनदेन शुरू करने और करने के लिए स्वतंत्र होना चाहिए। या कभी-कभी नियंत्रक स्पष्ट लेनदेन नियंत्रण से बच सकता है, और मॉडल को प्रत्येक परिवर्तन को स्वतः करने की अनुमति देता है।
लेकिन मुद्दा यह है कि कौन से लेन-देन आवश्यक हैं, इसके बारे में जानकारी कुछ ऐसी है जो मॉडल को नहीं पता - उन्हें बताया जाना चाहिए ($ लेनदेन संबंधी पैरामीटर के रूप में) या फिर इसे अपने कॉलर से पूछें, जो किसी भी तरह नियंत्रक की कार्रवाई तक प्रश्न को सभी तरह से सौंपना होगा।
आप एक सेवा परत भी बना सकते हैं प्रत्येक वर्ग को पता है कि ऐसे जटिल उपयोग के मामलों को कैसे निष्पादित करना है, और क्या एक ही लेनदेन में सभी परिवर्तनों को शामिल करना है। इस तरह आप बहुत सारे बार-बार कोड से बचते हैं। लेकिन PHP ऐप्स के लिए एक विशिष्ट सेवा परत शामिल करना आम बात नहीं है; नियंत्रक की कार्रवाई आमतौर पर सेवा परत के साथ मेल खाती है।