【问题标题】:DQL to join on property of a propertyDQL 加入属性的属性
【发布时间】:2013-07-02 17:44:45
【问题描述】:

我正在尝试通过测试属性的属性来创建 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;
}

概念逻辑是将 Roles 与 Jobs 连接起来,测试当前 Role 是 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.

【问题讨论】:

    标签: symfony doctrine-orm dql


    【解决方案1】:

    我想通了。有可能...您需要先加入子对象才能使用它们。我不得不改变我的加入顺序,我对我的过滤器在 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 个连接让我们为属于链接实体的对象设置别名,以便我们可以使用它们进行比较。

    这个 DQL 如何工作的“30,000 英尺视图”是这样的:

    • Foreach 角色
    • 此角色是否属于用户?
    • 为我们想要的工作获取角色
    • 该角色的别名
    • 角色备份的别名
    • 此角色是作业角色还是作业角色的备份角色?

    有点奇怪,但一旦你得到它就相当简单。

    【讨论】:

      猜你喜欢
      • 2015-05-19
      • 1970-01-01
      • 1970-01-01
      • 2015-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多