2013-07-02 29 views
2

我想通过测试属性的属性来创建一个DQL查询。其目标是创建一个DQL查询,以指示用户履行作业的角色,如果用户没有适当的角色则不返回行。DQL加入属性的属性

我的实体是角色,工作和用户。用户具有角色,作业需要一个角色(来完成他们),角色有'替代'链接到可以填补该角色的另一个角色。

存根的entites的版本是这样的:

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成为双向自连接并从这个方向进行攻击。学说不喜欢天真的尝试,所以看起来好像是使用了这种机智,需要新的DQL。

改变DQL到WITH j = :j AND j.jobRole = r OR j.jobRole = r.roleIBackUp yeilds新的错误:A single-valued association path expression to an inverse side is not supported in DQL queries. Use an explicit join instead.

回答

2

我想通了。有可能......您需要先加入子对象才能使用它们。我不得不改变我的连接顺序,而且我的筛选器不在WITH WITH子句中,而不是WHERE,但我很不满意,但很难与结果争论!

  SELECT r 
      FROM SystemBundle:Role r 
      LEFT JOIN UserBundle:User u 
      WITH u = :emp 
      INNER JOIN ProcessBundle:Job j 
      WITH j = :job 
      JOIN j.jobRole jr 
      JOIN jr.backUpRole jrbr 
      WHERE (jr = ar OR jrbr = ar) AND r MEMBER OF u.role 

最后2个连接让我们别名属于链接实体的对象,以便我们可以使用它们进行比较。

的 “¥30,000英尺观” 这个DQL如何运作是这样的:

  • 的foreach角色
  • 这是否属于角色的用户?
  • 获得作业中的作用,我们希望
  • 别名角色
  • 别名角色备份
  • 是这个角色的工作的角色或工作的角色的备份角色?

有点奇怪,但很简单,一旦你得到它。