symfony - association mapping when one entity isn't managed by Doctrine -
i have 2 entities in one-to-one association. first, person
, stored in mysql database , handled doctrine. second, aduserrecord
, describes activedirectory user record. read-only. not need know person
. also, aduserrecord
properties should never stored in mysql db privacy reasons.
an aduserrecord
retrieved using service, adsearcher
, can search samaccountname
or objectguid
. whenever search successful, service checks see if there corresponding person
record , creates 1 if there not. works fine.
my problem occurs when start person
object. mostly, don't need access person
's aduserrecord
i'd prefer not query active directory unless it's required. means, think, person::getadrecord()
needs have access adsearcher
service. this:
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; }
i've been reading symfony docs pretty assiduously, i'm still stumped.
questions
- how service entity? should injected via constructor, or it's needed, in getter? if occurs in getter, have inject or there way import it?
- is adding service entity canonical way of handling these types of situations? preferable build entity manager
aduserrecord
s? - what interfaces need implement if have build entity manager?
person
class
namespace acrd\defaultbundle\entity; use symfony\component\validator\constraints assert; use doctrine\orm\mapping 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 , setters }
it looks doctrine's postload
event best solution.
// src/acme/demobundle/eventlistener/activedirectorysubscriber.php namespace acme\demobundle\eventlistener; use acme\demobundle\model\adawareinterface; use doctrine\common\eventsubscriber; use doctrine\orm\event\lifecycleeventargs; // 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); } } }
you mentioned of time don't need use active directory stuff. before optimizing highly suggest measure how of performance impact there is. if, however, notice performance problem, consider using proxy object mitigate adperson
searching right point need it.
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)); }
the adpersonproxy
extend adperson
class, wrap each , every public method call load actual adperson
object , act facade between two. consider following implications before start coding though:
- it adds complexity codebase (the more code, more there maintain);
- it pain debug - example might exception inside template leave scratching head long time (been there, done that);
the bottom line in theory services should (mostly) not injected inside entities.
Comments
Post a Comment