2015-01-04 3 views
7

मैं सिम्फोनी 2.3 और php सिद्धांत 2.अलग व्यापार तर्क पीएचपी सिद्धांत 2

कार्यक्रम निम्नलिखित मॉडल का उपयोग से:

  • इकाई व्यवस्था - एक विशिष्ट ग्राहक आदेश
  • इकाई BadOrderEntry (खेतों : आईडी, आदेश - आदेश के साथ यूनिडायरेक्शनल एक-से-एक संबंध, createdAt) निर्माण इकाई BadOrderEntry
  • भंडार BadOrderEntryReposi के लिए
  • कारखाने BadOrderEntryFactory संस्था की खोज के तरीकों के लिए टोरी BadOrderEntry
  • /बचाने
  • प्रबंधक BadOrderEntryManager के लिए/संपादन इकाई के तरीकों को नष्ट BadOrderEntry
  • और मुख्य श्रेणी BadOrderList - बुरा आदेशों की सूची, इस वर्ग के कोड:

    private $factory; 
    private $repository; 
    private $manager; 
    
    public function __construct(
        BadOrderEntryFactory $f, 
        BadOrderEntryRepository $r, 
        BadOrderEntryManager $m 
    ) { 
        $this->factory = $f; 
        $this->repository = $r; 
        $this->manager = $m; 
    } 
    
    public function has(Order $order) 
    { 
        return $this->repository->existsByOrder($order); 
    } 
    
    public function add(Order $order) 
    { 
        if (! $this->has($order)) { 
         $entry = $this->factory->create($order); 
         $this->manager->save($entry); 
        } 
    } 
    
    public function remove(Order $order) 
    { 
        $entry = $this->repository->findOneByOrder($order); 
        if ($entry !== null) { 
         $this->manager->delete($entry); 
        } 
    } 
    

मुझे वास्तव में इस कक्षा के डिजाइन पसंद है। मैंने इसके बारे में बहुत कुछ सोचा। सबकुछ अद्भुत है। परंतु! एक समस्या है: लेनदेन में विधियों को जोड़ने और निकालने के तरीकों में संचालन किया जाना चाहिए। पीएचपी Docrine 2 में

लेन-देन कोड इस तरह दिखता है:

<?php 
$em->getConnection()->beginTransaction(); 
try { 
    //... do some work 
    $em->getConnection()->commit(); 
} catch (Exception $e) { 
    $em->getConnection()->rollback(); 
    throw $e; 
} 

लेकिन मैं BadOrderList अंदर इस कोड को कैसे फोन कर सकते हैं?

मैं बहुत समय बिताया है और हटाया डेटाबेस के आधार पर (और तदनुसार पीएचपी सिद्धांत 2), और इसे फिर से बनाने के लिए? अब कक्षाओं में निर्भरता BadOrderEntryRepository और BadOrderEntryManager में छिपी हुई है।

कैसे वर्ग BadOrderList में लेन-देन तंत्र पर निर्भरता को छिपाने के लिए?

+0

अपने 'प्रबंधक :: add' के लेन-देन प्रबंधन जोड़ें और' delete'I भी आप पर पुनर्विचार करने की सलाह है कि आपके डिज़ाइन। यह वास्तव में अच्छा नहीं है। अपने मॉडल को लगातार स्वतंत्र बनाओ। – Ziumin

+0

@Ziumin मैं प्रबंधक :: जोड़ें (या हटाएं) में लेनदेन प्रबंधन कैसे जोड़ सकता हूं? क्या डिजाइन समस्याएं? प्रबंधक बस ऑब्जेक्ट मैनेजर प्रबंधक पर अमूर्तता की एक अतिरिक्त परत है। यह बुरा नहीं है और यह अच्छा नहीं है। लेकिन अधिक नियंत्रण देता है। – stalxed

+0

आप इसे उसी तरह से कर सकते हैं जैसा आपने अपने उदाहरण में उल्लेख किया है। http://doctrine-orm.readthedocs.org/en/latest/reference/transactions-and-concurrency.html#approach-2-explicitly। डिजाइन समस्याओं के लिए - आपको क्यों लगता है कि आपकी सूची मुख्य वस्तु है। आप वास्तुकला के किस हिस्से के लिए मुख्य? क्या आपने विधि और कक्षा के नामों के बारे में सोचा है? क्या आप सिद्धांत के बिना अपने पूरे मॉडल का परीक्षण कर सकते हैं? – Ziumin

उत्तर

4

हमारी चर्चा के बाद मैं अपने प्रश्न का उत्तर है। प्रश्न वास्तव में नहीं है "कक्षा BadOrderList में लेनदेन तंत्र पर निर्भरता कैसे छिपाना है?", लेकिन एक दृढ़ता परत से एक मॉडल को डीक्यूपल कैसे करें? (उस विशेष मामले में सिद्धांत 2)।

मैं कुछ कोड

class BadOrderEntry 
// Bad - is too bad word to describe an order here. Why is it bad? Is it Declined? Cancelled? 
{ 
    private $order; 
    // some code 
} 
class BadOrderEntryFactory 
{ 
    // If there is not to much processing to build BadOrderEntry better use factory method like BadOrderEntry::fromOrder($order); 
} 
class BadOrderEntryRepository 
{ 
    // here is some read model 
} 
class BadOrderEntryManager 
// ITS a part of our model and shouldn't be coupled to ORM 
{ 
    public function save(BadEntry $be) 
    { 
    // some model events, model actions 
    $this->doSave($be); // here we should hide our storage manipulation 
    } 

    protected function doSave($be) // it can be abstract, but may contain some basic storage actions 
    { 
    } 

    // similar code for delete/remove and other model code 
} 
class ORMBadOrderEntryManager extends BadOrderEntryManager 
// IT'S NOT the part of your model. There is no business logic. There is only persistent logic and transaction manipulation 
{ 
    protected $entityManager; 

    // some constructor to inject doctrine entitymanager 

    protected doSave($be) 
    { 
    $em = $this->entityManager; 
    $em->getConnection()->beginTransaction(); // suspend auto-commit 
    try { 
     $em->persist($be); 
     $em->flush(); 
     $em->getConnection()->commit(); 
    } catch (Exception $e) { 
     $em->getConnection()->rollback(); 
     throw $e; 
    } 
    } 
} 
// You can also implement ODMBadOrderEntryManager, MemcacheBadOrderEntryManager etc. 

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

BadEntryBundle 
| 
+ Entity 
| | 
| --- BadOrderEntryEntity.php 
| 
+ ORM 
| | 
| --- ORMBadOrderEntryManager.php 

और फिर आप बस अपने BadOrderEntryList को ORMBadOrderEntryManager इंजेक्षन जाएगा

+0

यह वास्तव में अच्छा समाधान है! मैंने JMSPaymentCoreBundle में एक समान समाधान देखा है। लेकिन इसके बारे में नहीं सोचा ... तुमने मेरी आँखें खोली! आपको बहुत - बहुत धन्यवाद! – stalxed

1

आप एक सेवा के रूप में अपने वर्ग को बदलने और इसे कहते अपने वर्ग के भीतर आपकी सेवा कंटेनर इंजेक्शन लगाने के बाद जो कुछ भी आप चाहते हैं कर सकते हैं। आप यहाँ dependency injection बारे में अधिक जानकारी पा सकते हैं:

$injectedContainerOfService->get("id_of_your_service") 
+0

Thx। यह बहुत ही सरल और स्पष्ट समाधान है। लेकिन व्यावहारिक/टेस्टेबल/रखरखाव नहीं है। – Ziumin

+0

इसके व्यावहारिक और टेस्टेबल लेकिन इसके लिए आपको अपने नियंत्रक को डीक्यूपल करना चाहिए और इसे एक सेवा के रूप में बदलना चाहिए यदि आप इसका परीक्षण करना चाहते हैं – lsroudi

+0

आप नियंत्रक कहां देखते हैं? – Ziumin

संबंधित मुद्दे