Я нахожусь в Доктрине 2.3. У меня есть следующий запрос:
$em->createQuery(' SELECT u, c, p FROM Entities\User u LEFT JOIN u.company c LEFT JOIN u.privilege p WHERE u.id = :id ')->setParameter('id', $identity)
Затем я беру это, получаю результат (который представляет собой массив, я просто беру первый элемент) и запускаю detach $em->detach($result);
,
Когда я выхожу из кэша (используя драйвер кэша APC от Doctrine), я делаю:
$cacheDriver = new \Doctrine\Common\Cache\ApcCache(); if($cacheDriver->contains($cacheId)) { $entity = $cacheDriver->fetch($cacheId); $em->merge($entity); return $entity; }
Я надеюсь, что это позволит повторно включить загрузку отношений в объект, поскольку существует много других отношений, связанных с объектом User, отличным от того, что показано в этом запросе.
Я пытаюсь создать новый объект вроде этого:
$newEntity = new Entities\ClientType(); $newEntity['param'] = $data; $newEntitiy['company'] = $this->user['company']; $em->persist($newEntity); $em->flush();
Когда я это сделаю, я получаю сообщение об ошибке:
A new entity was found through the relationship 'Entities\ClientType#company' that was not configured to cascade persist operations for entity: Entities\Company@000000005d7b49b500000000dd7ad743. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'Entities\Company#__toString()' to get a clue.
Это отлично работает, когда я не использую объект компании под пользовательским объектом, который я получил из кеша. Есть ли способ сделать эту работу, поэтому мне не нужно возвращать объект компании из базы данных каждый раз, когда я хочу использовать ее в отношениях с новым объектом?
Изменить: это то, что у меня есть в моей пользовательской сущности, связанной с этими двумя отношениями:
/** * @ManyToOne(targetEntity="Company" , inversedBy="user", cascade={"detach", "merge"}) */ protected $company; /** * @ManyToOne(targetEntity="Privilege" , inversedBy="user", cascade={"detach", "merge"}) */ protected $privilege;
Я все еще получаю ту же ошибку.
Второе редактирование: попытка использования $em->contains($this->user);
и $em->contains($this->user['company']);
оба возвращают false. Что звучит … неправильно.
При объединении пользователя вы хотите, чтобы связанная с ним компания и Привилегия были объединены, правильно?
Этот процесс называется каскадным:
В свой пользовательский объект поместите cascade={"merge"}
в аннотацию @ManyToOne
(или другой тип определения определения, который вы используете) для $company
и $privilege
.
И если вы хотите, чтобы вызов отсоединения также был каскадным (что рекомендуется), введите cascade={"detach", "merge"}
.
ps: Не ставьте такие каскады с обеих сторон одной ассоциации, вы создадите бесконечный цикл;)
Редактировать:
Этот фрагмент кода:
$entity = $cacheDriver->fetch($cacheId); $em->merge($entity); // <- return $entity;
должно быть:
$entity = $cacheDriver->fetch($cacheId); $entity = $em->merge($entity); // <- return $entity;
Дело с merge()
заключается в том, что он оставляет объект, который вы передаете, в качестве аргумента нетронутым, и возвращает новый объект, представляющий управляемую версию объекта. Поэтому вы хотите использовать возвращаемое значение, а не аргумент, который вы передали.