My Doctrine based backend application has entity types Lead
and Contact
. One Lead
can have many Contact
s. My problem is that I want to keep contacts in the lead object's $contacts
property, but when I fetch the lead I already have the related contacts, because I already needed them earlier in a different context. So I want to attach the already fetched contacts to the newly fetched lead object manually.
Here is the problem in the detail:
The query for fetching lead contacts must consider some important points, e.g.:
User
)disabled
entriesSo there is a respective function getContactsByLead()
which is called by the frontend via a web service:
$qb = $repo->createQueryBuilder('c');
$qb->where($qb->expr()->eq('c.lead', '?0'));
$qb->setParameter(0, $leadId);
$qb->andWhere('c.disabled = 0');
$qb->andWhere($qb->expr()->eq('c.user', '?1'));
$qb->setParameter(1, $this->getUser()->getId());
return $qb->getQuery()->execute();
Currently there is another function getLeadWithContacts()
which should provide a Lead
object instead with those contacts in stored in its contacts
property:
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\LeadContact", mappedBy="lead")
*/
protected $contacts;
So this function getLeadWithContacts()
contains a query that is very similar to getContactsByLead()
, but fetches a lead instead and LEFT JOIN
s the contacts with the same conditions:
$qb = $this->createQueryBuilder('l');
$qb->leftJoin('l.contacts', 'c', Expr\Join::WITH, 'c.disabled = 0');
$qb->addSelect('c');
$qb->where($qb->expr()->eq('l.id', $leadId));
$qb->andWhere($qb->expr()->eq('c.user', '?0'));
$qb->setParameter(0, $this->getUser()->getId());
return $qb->getQuery()->getOneOrNullResult();
This is problematic, as the developer has to always make sure both functions respect the conditions in the same way. It already lead to bigger problems, when a developer forgot to adjust one of the queries when the conditions changed.
That's why I want to replace getLeadWithContacts()
with something like this:
public function getLeadWithContacts($leadId) {
$lead = $this->getLead($leadId);
$contacts = $this->getContactsByLead($lead);
$lead->setContacts($contacts);
return $lead;
}
But doctrine doesn't provide a setter method for the whole collection. And at this point, I also wonder if it works if I implement it on my own. Or would this lead to side effects, especially when I store the lead object again to the database later? I'm afraid of getting side effects like duplicate contacts and noticing them when it's too late. That's why I'm asking here...