我正在尝试创建Symfony Bundle,其中定义的实体可用于一对多/多对一的关系,而无需手动重写映射。动态映射manyToOne关系
我这样做是通过订阅loadClassMetadata
事件并添加基于它们实现的接口的映射。这并不像使用ResolveTargetEntityListener
那么简单,因为它只是简单地将接口替换为具体的类。
一个例子。我有一个地址和一个客户实体。客户有很多地址。 但是另一个包可能会重新定义客户(或者可能有多个地址的完全不同的实体)。为此,客户实施了AddressableInterface
。为了便于使用,我在特性中实现了这个接口。
在用户中,我检查该类是否实现了AddressableInterface
。如果是这样,则将OneToMany添加到Address
,并将ManyToOne添加到实现AddressableInterface
的类。 (在这个例子中Customer
类)
然而这留下了以下错误:
The association Entity\Customer#addresses refers to the owning side field Entity\Address#subject which does not exist.
但我设置到协会在我的用户两种方式。
下面是我的代码的本质。
namespace Entity;
class Address
{
public $subject;
}
namespace Entity;
class Customer implements AddressableInterface
{
use Traits/Addressable;
}
namespace Traits;
trait Addressable //Implements all methods from AddressableInterface
{
protected $addresses;
public function getAddresses()
{
return $this->addresses;
}
public function addAddress(AddressInterface $address)
{
$this->addresses->add($address);
}
public function removeAddress(AddressInterface $address)
{
$this->addresses->removeElement($address);
}
}
而事件订阅
class DynamicAddressBindingSubscriber implements EventSubscriber
{
public function getSubscribedEvents()
{
return [Events::loadClassMetadata];
}
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$metadata = $eventArgs->getClassMetadata();
$class = $metadata->getReflectionClass();
if (!in_array(AddressableInterface::class, $class->getInterfaceNames())) {
return;
}
$factory = new \Doctrine\ORM\Mapping\ClassMetadataFactory;
$factory->setEntityManager($eventArgs->getEntityManager());
$addressMetadata = $factory->getMetadataFor(Address::class);
$addressMetadata->mapManyToOne(
[
"targetEntity" => $class->getName(),
"fieldName" => "subject",
"inversedBy" => "addresses"
]
);
$metadata->mapOneToMany(
[
'targetEntity' => Address::class,
'fieldName' => 'addresses',
'mappedBy' => 'subject'
]
);
}
}
我已经看了多个例子并根据我的大部分上this article代码和教条捆绑源。但是我坚持这一点,因为我不知道协会为什么找不到欠款方。
尼斯的问题,我只是想知道,如果你真的需要反向关系。否则,您不需要增加“地址”的元数据。此外,如果多个实体在同一应用程序中具有地址(例如公司,人员),则它们将避免冲突,它们不能由“主体”映射)。 – fejese 2014-10-08 09:15:41
确实看起来不像我需要反向关系,当我删除“Address”的元数据时,错误仍然保持不变。 – Waaghals 2014-10-08 09:28:44
您是否已从'mapOneToMany'调用中移除'mappedBy'选项? – fejese 2014-10-08 09:31:46