2016-03-10 14 views
6

Bir hedef öğeyi birden çok varlık yöneticisi üzerinden çözümlemek mümkün müdür?Hedef Varlığı Birden Çok Varlık Yöneticisi ile Çözümleme

/** 
* 
* @ORM\Entity 
* @ORM\Table(name="my_vendor_person") 
*/ 
class Person 
{ 
    /** 
    * Unique Id 
    * 
    * @var integer $id 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    /** 
    * First Name 
    * 
    * @var string $name 
    * 
    * @ORM\Column(name="first_name", type="string", length=32) 
    */ 
    protected $firstName; 
    // etc... 

Ve (benim ana uygulamasında) bir sınıf kullanıcı:

/** 
* @ORM\Entity 
* 
* @ORM\Table(name="my_financial_user") 
* 
*/ 
class User extends BaseUser 
{ 

    /** 
    * @ORM\OneToOne(targetEntity="My\FinancialBundle\Model\PersonInterface") 
    * @var PersonInterface 
    */ 
    protected $person; 

Temelde çift kullanıcı istiyorum

Bir sınıf (yeniden kullanılabilir paket içinde) kişi var Yeniden kullanılabilir paketten bir kişiye.

doctrine: 
    orm: 
     auto_generate_proxy_classes: "%kernel.debug%" 
     default_entity_manager: default 
     resolve_target_entities: 
      My\FinanceBundle\Model\PersonInterface: My\VendorBundle\Entity\Person 
     entity_managers: 
      default: 
       naming_strategy: doctrine.orm.naming_strategy.underscore 
       connection: default 
       mappings: 
        MyFinanceBundle: ~ 
      second: 
       naming_strategy: doctrine.orm.naming_strategy.underscore 
       auto_mapping: false 
       connection: second 
       mappings: 
        MyVendorBundle: ~ 
        MyVendorUserBundle: ~ 

Ayrıca ana paket içinde kullanıcı sınıfı, satıcı paket içinde bir baz kullanıcıyı uzatır: Ben o bana bunu sağlayan düşünce öğretinin yapılandırmasında çözülmesine hedef varlık seçeneği batmıştı

. Ana uygulamalarda db kullanıcı sınıfı korunur.

Bu yapılandırmada bana bir hata veriyor.

[Doctrine\Common\Persistence\Mapping\MappingException]                      
The class 'My\VendorBundle\Entity\Person' was not found in the chain configured namespaces My\FinanceBundle\Entity, FOS\UserBundle\Model 

Bunu nasıl çözeceğini bilen var mı?

+1

İlgili soruları görmek için: http://stackoverflow.com/questions/14403863/entities-associations-across-different-managers ve http://stackoverflow.com/questions/9330018/issues-in-entities-from- farklı-bundles-kullanarak-farklı-varlık-yöneticileri – takeit

+1

Nope. Varlık yöneticileri birbirleriyle konuşmuyorlar. Tüm gerekli varlıkları tek bir varlık yöneticisine dahil etmenin bir yolunu bulmanız gerekecektir. – Cerad

+0

bu talihsiz bir durumdur. Bence bu yasal bir kullanıcı vakası, gelecekte de umut desteği olacak. Hem yorumunuz için teşekkürler.Şimdilik yapacağım şey, kullanıcının gerekli olduğu yerde denetleyicilere kullanıcı tarafından dinamik olarak atanmasıdır ($ user = $ this-> getUser(); $ user-> kişi = $ kişi) – apfz

cevap

3

Yorumda belirtildiği gibi, varlık yöneticileri birbirleriyle konuşmuyor, bu yüzden etrafta çalışmak zorundasınız. Bir yol bir doktrin dinleyicisi kullanmak ve getPerson yöntemi tarafından çağrılabilir bir geri arama eklemek.

AppBundle \ Doktrin \ InsertPersonListener

use Doctrine\Common\Persistence\Event\LifecycleEventArgs; 
use My\FinancialBundle\Entity\Person; 
use My\VendorBundle\Entity\User; 
use Symfony\Bridge\Doctrine\RegistryInterface; 

class InsertPersonListsner 
{ 
    /** 
    * @var RegistryInterface 
    */ 
    private $registry; 

    /** 
    * Insert the registry into the listener rather than the entity manager 
    * to avoid a cyclical dependency issue 
    * 
    * @param RegistryInterface $registry 
    */ 
    public function __construct(RegistryInterface $registry) 
    { 
     $this->registry = $registry; 
    } 

    /** 
    * On postLoad insert person callback 
    * 
    * @var LifecycleEventArgs $args 
    */ 
    public function postLoad(LifecycleEventArgs $args) 
    { 
     $user = $args->getObject(); 

     // If not a user entity ignore 
     if (!$user instanceof User) { 
      return; 
     } 

     $reflectionClass = new \ReflectionClass(User::class); 

     $property = $reflectionClass->getProperty('personId'); 
     $property->setAccessible(true); 

     // if personId is not set ignore 
     if (null === $personId = $property->getValue($user)) { 
      return; 
     } 

     // get the repository for your person class 
     // - changed to your version from the comments 
     $repository = $this->registry 
      ->getManagerForClass(Person::class) 
      ->getRepository('MyVendorBundle:Person'); 

     // set the value as a callback rather than the entity 
     // so it's not called unless necessary 
     $property = $reflectionClass->getProperty('personCallback'); 
     $property->setAccessible(true); 
     $property->setValue($user, function() use ($repository, $personId) { 
      return $repository->find($personId); 
     }); 
    } 
} 

My \ VendorBundle \ Varlık \ Kullanıcı

use My\FinancialBundle\Entity\Person; 

class User 
{ 
    //.. 

    /** 
    * @var Person 
    */ 
    private $person; 

    /** 
    * @var integer 
    */ 
    private personId; 

    /** 
    * @var callable 
    */ 
    private $personCallback; 

    /** 
    * Set person 
    * 
    * @param Person|null $person 
    * @return $this 
    */ 
    public function setPerson(Person $person = null) 
    { 
     $this->person = $person; 

     // if the person is null reset the personId and 
     // callback so that it's not called again 
     if (null === $person) { 
      $this->personId = null; 
      $this->personCallback = null; 
     } else { 
      // set the personId to be stored on the db for the next postLoad event 
      $this->personId = $person->getId(); 
     } 

     return null; 
    } 

    /** 
    * Get person 
    * 
    * @return Person|null 
    */ 
    public function getPerson() 
    { 
     // if the person has not been set and the callback is callable, 
     // call the function and set the result (of $repository->find($personId)) 
     // to the person property and then return it. The callback is 
     // reset to stop unnecessary repository calls in case of a null response 
     if (null === $this->person && is_callable($this->personCallback)) { 
      $this->person = call_user_func($this->personCallback); 
      $this->personCallback = null; 
     } 

     return $this->person; 
    } 
} 

AppBundle \ Resources \ services.yml

app.listener.insert_person: 
    class: AppBundle\Doctrine\InsertPersonListener 
    arguments: 
     - '@doctrine' 
    tags: 
     - { name: doctrine.event_listener, event: postLoad } 

GÜNCELLEME

gerçek hayatta bu bir örnek arayan sonra ben this buldum. Bundan sana yük başına bir az new \ReflectionClass(...) çağrıyı anlamına geleceğini sanıyorum,

$reflectionClass = $args->getObjectManager() 
    ->getClassMetadata(User::class) 
    ->reflClass 

e

$reflectionClass = new \ReflectionClass(User::class) 

değişebileceğini gördük.

+0

Bu gerçekten çok iyi! sadece pratik bir cevap değil, çok şey öğrendim. Bunu gönderdiğiniz için teşekkürler. Umarım bu aynı problemle karşılaşan diğerlerine yardım eder. – apfz

+0

PostLoad, $ property-> getValue ($ user) değerinde, $ user-> getValue ($ entity) olmalı, $ kullanıcı tanımlı değil. Ayrıca $ args-> getEntity(), getEntity kullanımdan kaldırıldığı için $ args-> getObject() olabilir. – apfz

+0

Benim hatam. Bir sebepten dolayı, bunları gerçekten açıkça ortaya koyacak bir IDE kullanmak yerine doğrudan metin kutusuna yazmaya karar verdim. Ayrıca $ varlık '$ user' olarak değiştirdim, bu yüzden daha açık ve unuttum 'services.yml' config dosyasını ekledi. – qooplmao