我在一对一关联中有2个实体。第一个Person
存储在MySQL数据库中,由Doctrine处理。第二个AdUserRecord
描述了ActiveDirectory用户记录。它是只读的。它不需要知道Person
。此外,出于隐私原因,永远不应将AdUserRecord
属性存储在MySQL数据库中。
使用AdUserRecord
服务检索AdSearcher
,该服务可以samaccountname
或objectGUID
进行搜索。只要搜索成功,服务就会检查是否有相应的Person
记录,如果没有,则创建一个。这很好。
当我使用Person
对象开始时出现问题。大多数情况下,我不需要访问Person
的{{1}},因此除非需要,否则我不想查询Active Directory。这意味着,我认为AdUserRecord
需要访问Person::getAdrecord()
服务。像这样:
AdSearcher
我一直在努力阅读Symfony文档,但我仍然感到难过。
public function getAdrecord(){
if($this->adrecord) return $this->adrecord;
$searcher = ???; //get AdSearcher service somehow
$record = $search->getRecordByUserGuid($this->ad_guid);
if(!$record) throw new \Exception('this person no longer exists');
$this->adrecord = $record;
return $this->adrecord;
}
s AdUserRecord
上课
Person
答案 0 :(得分:1)
看起来Doctrine的postLoad
event是最好的解决方案。
// src/Acme/DemoBundle/EventListener/ActiveDirectorySubscriber.php
namespace Acme\DemoBundle\EventListener;
use Acme\DemoBundle\Model\AdAwareInterface;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
// for doctrine 2.4: Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use Symfony\Component\DependencyInjection\ContainerAware
class ActiveDirectorySubscriber extends ContainerAware implements EventSubscriber
{
public function getSubscribedEvents()
{
return array(
'postLoad',
);
}
public function postLoad(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if (!($entity instanceof AdAwareInterface)) {
return:
}
$adSearcher = $this->getContainer()->get('acme_demo.ad_searcher');
if ($adPerson = $adSearcher->find($entity->getAdGuid())) {
$entity->setAdPerson($adPerson);
}
}
}
您还提到大多数时候您不需要使用活动目录。在优化之前,我强烈建议您实际测量有多少性能影响。但是,如果您确实注意到性能问题,请考虑使用代理对象将AdPerson
搜索权限降低到您实际需要的位置。
public function postLoad(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if (!($entity instanceof AdAwareInterface)) {
return:
}
$adSearcher = $this->getContainer()->get('acme_demo.ad_searcher');
$entity->setAdPerson(new AdPersonProxy($adSearcher));
}
AdPersonProxy
基本上会从您的AdPerson
类扩展,通过调用来包装每个公共方法以加载实际的AdPerson
对象,然后充当两者之间的外观。在开始编码之前,请考虑以下含义:
最重要的是,理论上服务应该(大部分)不应该注入实体内部。
答案 1 :(得分:0)
关于你的第三个问题:
EntityManagers实施Doctrine/Common/Persistence/ObjectManager
- 查看the interface on github。
此外:
一个有点干净的实现类似于gedmo/doctrine-extensions提供的Document< - > Entity映射(称为 references )。
如果您想要的话,请开始深入研究ReferenceListener的代码:)