【问题标题】:Querying by multiple associations (OR) in CakePHP 3.0CakePHP 3.0 中的多个关联 (OR) 查询
【发布时间】:2014-12-19 16:48:41
【问题描述】:

我正在尝试使用 CakePHP 3.0 beta 3 构建一个(或多或少复杂的)查询。我有以下实体:

用户属于ToMany 组 任务 belongsToMany 用户(别名为“收件人”) 任务属于ToMany 组

这是一个任务管理系统。任务可以发给特定用户,也可以发给指定的用户组。

我现在正在尝试查找属于当前用户或当前用户所属组的任务(与特定用户相关的所有任务)。我得到了用户 ID 和用户所属的组列表。

我已经设法使用以下代码使其工作:

$queryOptions = [
    'contain' => [
        'Recipients', 'Groups'
    ]
];

$tasksForUser = $this->Tasks->find('all', $queryOptions)->matching('Recipients', function ($q) use ($user_id) {
    return $q->where(['Recipients.id' => $user_id]);
})->toArray();

$tasksForGroup = $this->Tasks->find('all', $queryOptions)->matching('Groups', function($q) use ($group_ids) {
    return $q->where(['Groups.id IN' => $group_ids]);
})->toArray();

$this->set('tasks', array_merge($tasksForUser, $tasksForGroup));

CakePHP 3.0 声称有一个复杂的 ORM 模型,那么有没有办法在单个查询中执行它?它可能使我能够即时过滤掉重复项。

提前致谢, 戴夫

【问题讨论】:

    标签: cakephp orm cakephp-3.0


    【解决方案1】:

    您需要两个查询的UNION。 ORM 支持此语句。默认情况下,MySQL 会清除重复的结果(假设 DISTINCT),所以你很高兴。

    Cake 的文档有 a nice example,它应该适用于您的案例,如下所示:

    $tasksForUser = $tasks->find()
        ->contain('Recipients', function ($q) use ($user_id) {
            return $q->where(['Recipients.id' => $user_id]);
        })
    ;
    
    $tasksForGroup = $tasks->find()
        ->contain('Groups', function($q) use ($group_ids) {
            return $q->where(['Groups.id IN' => $group_ids]);
        })
    ;
    
    $tasksForGroup->union($tasksForUser);
    

    因此,您只需将代码放入模型中,以便作为自定义查找从控制器调用。

    【讨论】:

    • 非常感谢,这很有帮助。首先,它抱怨两个查询具有不同数量的列,但我能够通过使用 select() 解决这个问题。然后我遇到了一个奇怪的问题:我无法让 contains() 在最终结果中同时包含 Recipients 和 Groups 关联。使用 $tasksForGroup->union($tasksForUser) 它只包括用户。将其切换到 $tasksForUser->union($tasksForGroup),它只包括组。我已经解决了这个问题,使用 union() 来获取任务 ID 列表并针对完整结果集发出第二个查询。
    • Unions require "compatible" results(具有相同类型的相同字段)。也许这可以解释为什么它会放弃你的领域。一个好的策略确实是获取 id 并使用它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多