Я пытаюсь создать запрос DQL, проверяя свойство свойства. Цель состоит в том, чтобы создать запрос DQL, который будет указывать, в какой роли пользователь выполняет задание, не возвращая строк, если у пользователя нет надлежащей роли.
Моими сущностями являются Роль, Работа и Пользователь. У пользователей есть роли, заданиям требуется роль (для их выполнения), а у ролей есть «заместители», которые связаны с другой ролью, которая может заменить эту роль.
Заглушенные версии сущностей выглядят так:
class User {
//Annotation not needed for question
protected $id;
/**
* @var SystemBundle\Entity\Role
*
* @ORM\ManyToMany(targetEntity="SystemBundle\Entity\Role")
* @ORM\JoinTable(name="User_User__Role",
* joinColumns={
* @ORM\JoinColumn(name="User_ID", referencedColumnName="ID")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="Role_ID", referencedColumnName="ID")
* }
* )
*/
protected $roles;
}
class Job {
//Annotation not needed for question
protected $id;
/**
* @var SystemBundle\Entity\Role $jobRole
*
* @ORM\ManyToOne(targetEntity="Role")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="Role_ID", referencedColumnName="ID")
* })
*/
protected $jobRole;
}
class Role {
//Annotation not needed for question
protected $id;
/**
* @var SystemBundle\Entity\Role $jobRole
*
* @ORM\OneToOne(targetEntity="Role")
* @ORM\JoinColumn(name="BackupRole_ID", referencedColumnName="ID")
*/
protected $backUpRole;
}
Концептуальная логика состоит в том, чтобы объединить роли с заданиями, проверяя, является ли текущая роль job.JobRole или job.JobRole.backUpRole. Я пробовал это, и доктрине действительно не нравится job.jobRole.backUpRole, и она выдает эту ошибку во втором периоде:
[Syntax Error] line 0, col 210: Error: Expected =, <, <=, <>, >, >=, !=, got '.'
Моя попытка DQL выглядит так
SELECT r
FROM SystemBundle:Role r
INNER JOIN ProcessBundle:Job j
WITH j = :j AND j.jobRole = r OR j.jobRole.backUpRole = r
LEFT JOIN UserBundle:User u
WITH r MEMBER OF u.roles
WHERE u = :emp AND u IS NOT NULL
ORDER BY r.id
Я могу выполнить эту задачу с помощью чистого SQL, а также просто используя php для обхода ассоциаций, но я хочу оставаться верным использованию DQL (потому что это меня раздражает, и я хочу знать, можно ли это сделать).
Если это поможет, вот мой чистый SQL:
#get all roles
select r.*
from Sys_Role as r
inner join
#get the role assigned to the job
(select r.*
FROM Sys_Role as r
INNER JOIN Sys_Job as j
ON j.JobRole_ID = r.ID
WHERE j.ID = ?) as jr
#join roles based on the job-role's id or backup id
# this should filter the list of roles down to the role and backup role for the job
on ar.ID = aar.ID OR ar.ID = aar.BackUpRole_ID
# and filter by the roles the user is assigned
INNER JOIN User_User__Role as uur
ON r.ID = uur.Role_ID
WHERE uur.User_ID = ?
РЕДАКТИРОВАТЬ: Мои извинения. При редактировании макета вопроса я случайно удалил файл DQL. Я добавил это обратно в вопрос!
ОБНОВЛЕНИЕ: я изучаю возможность сделать $backUpRole двунаправленным самосоединением и атакую с этого направления. Doctrine не любит наивных попыток, поэтому похоже, что если используется этот такт, нужен свежий DQL.
Изменение DQL на WITH j = :j AND j.jobRole = r OR j.jobRole = r.roleIBackUp
приводит к новой ошибке: A single-valued association path expression to an inverse side is not supported in DQL queries. Use an explicit join instead.