2016-03-10 7 views
6

क्या एकाधिक इकाई प्रबंधकों पर लक्षित इकाई को हल करना संभव है?एकाधिक इकाई प्रबंधकों के साथ लक्ष्य इकाई को हल करें

/** 
* 
* @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... 

और एक वर्ग के उपयोगकर्ता (अपने मुख्य आवेदन में):

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

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

असल में मैं जोड़ी उपयोगकर्ता करना चाहते

मैं एक वर्ग व्यक्ति (एक फिर से प्रयोग करने योग्य बंडल में) है पुनः उपयोग करने योग्य बंडल से एक व्यक्ति को।

मैं सिद्धांत के विन्यास जो मैंने सोचा था कि यह मुझे यह करने के लिए अनुमति देता है में स्थापित किया था संकल्प लक्ष्य इकाई विकल्प:

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: ~ 

इसके अलावा, मुख्य बंडल में उपयोगकर्ता वर्ग, विक्रेता बंडल में एक आधार के उपयोगकर्ता फैली हुई है। पाठ्यक्रम के उपयोगकर्ता वर्ग को मुख्य अनुप्रयोग डीबी में बनाए रखा जाता है।

इस कॉन्फ़िगरेशन के साथ यह मुझे एक त्रुटि देता है।

[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 

क्या कोई इसे हल करने के बारे में जानता है?

+1

इन संबंधित प्रश्नों को देखें: http://stackoverflow.com/questions/14403863/entities-associations-across-different-managers और http://stackoverflow.com/questions/9330018/issues-in-entities-from- विभिन्न-बंडल-उपयोग-अलग-इकाई-प्रबंधक – takeit

+1

नहीं। इकाई प्रबंधक एक-दूसरे से बात नहीं करते हैं। आपको एक ही इकाई प्रबंधक में सभी आवश्यक इकाइयों को शामिल करने का एक तरीका ढूंढना होगा। – Cerad

+0

दुर्भाग्यपूर्ण है। मुझे लगता है कि यह वैध उपयोगकर्ता मामला है, उम्मीद है कि भविष्य में समर्थन होगा .. आपकी टिप्पणी के लिए धन्यवाद।अभी के लिए मैं क्या करूँगा गतिशील रूप से उपयोगकर्ता को उस नियंत्रक में उपयोगकर्ता को असाइन करें जहां इसकी आवश्यकता है ($ उपयोगकर्ता = $ यह-> getUser(); $ उपयोगकर्ता-> व्यक्ति = $ व्यक्ति) – apfz

उत्तर

3

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

AppBundle \ सिद्धांत \ 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); 
     }); 
    } 
} 

मेरे \ VendorBundle \ इकाई \ उपयोगकर्ता

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 \ संसाधन \ services.yml

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

अद्यतन

वास्तविक जीवन में इस का एक उदाहरण के लिए देखने के बाद मैं this पाया। इस से मैंने देखा कि आप

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

जो, मुझे लगता है, करने के लिए

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

बदल लोड प्रति एक कम new \ReflectionClass(...) कॉल का मतलब होगा सकता है।

+0

यह वाकई अच्छा है! न केवल एक व्यावहारिक उत्तर बल्कि बहुत सी सीखा। इसे पोस्ट करने के लिए धन्यवाद। उम्मीद है कि यह उन लोगों की मदद करेगा जो एक ही समस्या का सामना करते हैं। – apfz

+0

मुझे पोस्टलोड, $ संपत्ति-> getValue ($ उपयोगकर्ता) में मानते हैं, $ property-> getValue ($ इकाई) होना चाहिए, क्योंकि $ उपयोगकर्ता परिभाषित नहीं है। $ args-> getEntity(), $ args-> getObject() प्राप्त हो सकता है क्योंकि GetEntity को बहिष्कृत किया गया है। – apfz

+0

मेरा बुरा। किसी कारण से मैंने इसे आईडीई का उपयोग करने के बजाय सीधे टेक्स्ट बॉक्स में लिखने का फैसला किया जो इन सभी को वास्तव में स्पष्ट कर देता। मैंने '$ इकाई' का नाम बदलकर' $ उपयोगकर्ता' कर दिया है, इसलिए यह अधिक स्पष्ट है और 'services.yml' कॉन्फ़िगरेशन फ़ाइल जो मैं भूल गया था जोड़ा गया। – qooplmao

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