2015-01-04 20 views
7

ben symfony 2.3 ve php doktrinini programı aşağıdaki modelleri vardır 2.Ayırma iş mantığı PHP Doktrini 2

kullanmak den:

  • varlık al - Tipik bir müşteri siparişini
  • varlık BadOrderEntry (alanlar : id, sipariş - sipariş ile tek yönlü bire bir ilişki, createdAt) oluşturma varlık BadOrderEntry
  • depo BadOrderEntryReposi için
  • fabrika BadOrderEntryFactory

    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); 
        } 
    } 
    
: Kötü siparişlerin listesini, bu sınıfın kod - BadOrderEntry
  • VE ANA SINIFI BadOrderList/düzenle/kaydetme varlığın yöntemlerini silmek

  • yöneticisi BadOrderEntryManager için varlığın arama yöntemleri için Tory BadOrderEntry
  • Bu sınıfın tasarımını gerçekten çok seviyorum. Bunun hakkında çok düşündüm. Her şey harika. FAKAT! Tek bir sorun var: yöntemlerde işlemler ekleme ve çıkarma işlemleri gerçekleştirilmelidir. PHP Docrine 2'de

    İşlem kodu şuna benzer:

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

    Ama nasıl BadOrderList içinde bu kod çağırabilir?

    Çok fazla zaman harcadım ve veritabanına (ve buna karşılık PHP Doktrini 2) bağlı olarak kaldırdım ve tekrar oluşturmak için? Artık bağımlılık, BadOrderEntryRepository ve BadOrderEntryManager sınıflarında gizli.

    BadOrderList sınıfındaki işlem mekanizmasına bağımlılık nasıl gizlenir?

    +0

    delete'I da yeniden düşünmeye önermek 'senin' Yöneticisi :: add' işlem yönetimini ekleyin ve

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

    Ve o zaman sadece BadOrderEntryList için ORMBadOrderEntryManager enjekte edeceğiz senin tasarımı. Gerçekten hoş değil. Modelinizi kalıcı hale getirin. – Ziumin

    +0

    @Ziumin İşlem yönetimini Manager :: add (veya delete) öğesine nasıl ekleyebilirim? Hangi tasarım problemleri? Müdür, doktrin nesnesi yöneticisi üzerinde ek bir soyutlama katmanıdır. Kötü değil ve iyi değil. Fakat daha fazla kontrol sağlar. – stalxed

    +0

    Örneğinizde belirttiğiniz şekilde yapabilirsiniz. http://doctrine-orm.readthedocs.org/en/latest/reference/transactions-and-concurrency.html#approach-2- Açıkça. Tasarım sorunlarına gelince, neden listenizin ANA nesnesi olduğunu düşünüyorsunuz? Hangi mimarinin bir parçası için ana? Yöntem ve sınıf isimlerini düşündün mü? Bütün modelini doktrin olmadan test edebilir misin? – Ziumin

    cevap

    4

    Ben sorunuza bir cevabım var. Asıl soru şu: "BadOrderList sınıfındaki işlem mekanizmasının bağımlılığı nasıl gizlenir?", ancak Kalıcı katmandan bir model nasıl ayrıştırılır? (Bu durumda Doctrine2).

    Hepimizin modeliniz paket dışına taşındı ve her yerde kullanılabilir, dizin yapısı hakkında konuşmak ise

    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. 
    

    Yani bazı kod ile benim önerim göstermek çalıştı. Sizin Bundle yapısı gibi olacak:

    +0

    Bu gerçekten harika bir çözüm! JMSPaymentCoreBundle'da benzer bir çözüm gördüm. Ama düşünmedim ... Gözlerimi açtın! Çok teşekkür ederim! – stalxed

    1

    Sınıfınızı bir hizmet olarak dönüştürebilir ve servis kabınızı sınıfınızın içine enjekte ettikten sonra istediğiniz yere çağırabilirsiniz. Burada yaklaşık dependency injection fazla bilgi bulabilirsiniz: tartışmamızın ardından

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

    Thx. Bu çok basit ve açık bir çözümdür. Ama pratik/test edilebilir/sürdürülebilir değil. – Ziumin

    +0

    onun pratik ve test edilebilir ama bunun için denetleyicinizi ayrıştırmalı ve test etmek istiyorsanız bir hizmet olarak dönüştürmelisiniz – lsroudi

    +0

    Bir denetleyiciyi nerede görüyorsunuz? – Ziumin