是否可以通过多个实体管理器解析目标实体?
我有一个班级人员(在一个可重复使用的包中):
/**
*
* @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的配置中设置了解决目标实体选项,我认为它允许我这样做:
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: ~
此外,主包中的用户类扩展了供应商包中的基本用户。用户类当然是在主应用程序db中维护的。
使用此配置会给我一个错误。
[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
有谁知道如何解决这个问题?
答案 0 :(得分:3)
正如评论中所提到的,实体经理不会互相交谈,因此您必须解决这个问题。一种方法是使用一个doctrine监听器并插入一个可以由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 = new \ReflectionClass(User::class)
到
$reflectionClass = $args->getObjectManager()
->getClassMetadata(User::class)
->reflClass
我认为,这意味着每次加载会少new \ReflectionClass(...)
次呼叫。