Symfony 当一个实体不是';不受条令管理

Symfony 当一个实体不是';不受条令管理,symfony,associations,Symfony,Associations,我在一对一的关联中有两个实体。第一个名为Person,存储在MySQL数据库中,由Doctrine处理。第二个,AdUserRecord,描述ActiveDirectory用户记录。它是只读的。它不需要知道关于人的信息。此外,出于隐私原因,AdUserRecord属性不应存储在MySQL数据库中 使用服务AdSearcher检索AdUserRecord,该服务可以通过samaccountname或objectGUID进行搜索。只要搜索成功,服务就会检查是否有相应的人员记录,如果没有,则创建一条记

我在一对一的关联中有两个实体。第一个名为
Person
,存储在MySQL数据库中,由Doctrine处理。第二个,
AdUserRecord
,描述ActiveDirectory用户记录。它是只读的。它不需要知道关于
人的信息
。此外,出于隐私原因,
AdUserRecord
属性不应存储在MySQL数据库中

使用服务
AdSearcher
检索
AdUserRecord
,该服务可以通过
samaccountname
objectGUID
进行搜索。只要搜索成功,服务就会检查是否有相应的
人员
记录,如果没有,则创建一条记录。那很好

当我从
Person
对象开始时,问题就出现了。大多数情况下,我不需要访问
个人的
AdUserRecord
,因此我宁愿不查询Active Directory,除非它是必需的。这意味着,我认为,
Person::getAdrecord()
需要访问
AdSearcher
服务。大概是这样的:

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;
}
我一直在非常认真地阅读Symfony文档,但我仍然感到困惑

问题
  • 如何将服务放入实体中?它应该通过构造函数注入,还是只在需要的地方,在getter中注入?如果它只发生在getter中,我必须注入它还是有方法导入它
  • 向实体添加服务是否是处理此类情况的规范方法?是否最好为
    AdUserRecord
    s构建一个实体管理器
  • 如果必须构建实体管理器,我需要实现哪些接口
Person
class

namespace ACRD\DefaultBundle\Entity;

use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use ACRD\DefaultBundle\Entity\AdUserRecord;

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

    /**
     * @ORM\Column(name="AD_guid", type="string", length=36, unique=true)
     */
    protected $ad_guid;

    /**
     * @var AdUserRecord
     */
    protected $adrecord;

     //usual getters and setters
}
看来教条是最好的解决方案

// 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);
        }
    }
}

您还提到,大多数情况下,您不需要使用active directory。在优化之前,我强烈建议您实际测量性能影响的程度。但是,如果您确实注意到性能问题,请考虑使用代理对象来减轻<代码> ADMPEN/COD>搜索权限,直到您真正需要它的某个点。
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
对象,然后充当两者之间的门面。在开始编码之前考虑以下含义:

  • 它增加了代码库的复杂性(代码越多,需要维护的代码就越多)
  • 调试将是一件痛苦的事情——例如,您可能会在自己的系统中遇到异常 模板,会让你抓挠你的头很长一段时间(在那里, 这样做)


底线是,理论上,服务不应该(大部分)注入实体内部。

关于第三个问题:

EntityManager实现了
条令/通用/持久性/对象管理器
——请看一看

进一步:

一个稍微干净的实现类似于提供的DocumentEntity映射(称为引用)

浏览一下文档,看看它是如何工作的


如果这就是你想要的,开始深入研究:)

的代码会帮你弄明白吗?@cheesemacfly:我不太清楚在我的情况下,这可能会起什么作用。我的部分问题是,对于“正常”原则实体,我可以在注释中定义关系(例如
@ORM\OneToMany(targetEntity=“Note”,mappedBy=“experties”)
)。我想我不能用我的
AdUserRecord
做到这一点。我可以吗?我想你最好的办法是做一个人事经理,然后做$adRecord=$PersonManager->findAdRecord($person);这样,您就不必向不受欢迎的实体中注入服务。只需将adSearcher注入PersonManager即可。@Cerad:是否有关于构建实体管理器的文档?我找不到它。由于某种原因,当我在看到您的问题后阅读此文档时,它非常有意义。它真的不再是。。。