【问题标题】:CakePHP 3 contain select fieldsCakePHP 3 包含选择字段
【发布时间】:2015-06-25 17:02:54
【问题描述】:

我有以下数据库表:项目、用户、组、itemImages。 (items, groups) 和 (users, groups) 之间存在多对多关系,(items, itemImages) 之间存在一对多关系。 所有适当的外键都已在 CakePHP 中设置为关联。

如何使用 contains() 构造一个查询,该查询选择所有项目及其主图像,这些项目位于一个组中,该组已作为主组分配给具有特定 ID 的用户?

为了更清楚,下面是一个普通的 SQL 查询的样子:

SELECT items.id AS itemId, items.name, itemImages.url AS itemUrl
FROM items
INNER JOIN groups_items ON groups_items.item_id = items.id
INNER JOIN groups ON groups_images.group_id = groups.id
INNER JOIN groups_users ON groups_users.group_id = groups.id
INNER JOIN users ON groups_users.user_id = users.id
INNER JOIN itemImages ON itemImages.item_id = items.id
WHERE groups_users.isMainGroup = 1
    AND users.id = :userId
    AND itemImages.isMainImage = 1

我现在拥有的 CakePHP 代码:

$items = $this->Items->find()
            ->hydrate(false)
            ->contain([
                'Groups.Users' => function($q) use ($userId){
                    return $q->where(['isMainGroup' => 1, 'Users.id' => $userId]);
                },
                'ItemImages' => function($q){
                    return $q->where(['isMainImage' => 1]);
                },
            ]);
            //->select(['itemId' => 'Items.id', 'Items.name', 'itemUrl' => 'itemImages.url']);

【问题讨论】:

    标签: php mysql cakephp orm cakephp-3.0


    【解决方案1】:

    ma​​tching() 方法可以帮助解决这个问题

    $items = $this->Items->find()
            ->hydrate(false)
            ->select(['Items.id', 'Items.name', 'itemImages.url'])
            ->distinct(['Items.id'])
            ->matching('Groups.Users', function ($q) use ($userId) {
                return $q->where(['Groups.isMainGroup' => 1, 'Users.id' => $userId]);
            })
            ->matching('ItemImages', function ($q) {
                return $q->where(['ItemImages.isMainImage' => 1]);
            })
            ->contain([
                'ItemImages' => function ($q) {
                    return $q->autoFields(false)
                             ->select(['id','url'])
                             ->where(['ItemImages.isMainImage' => 1]);
                }
            ]);
    

    我认为,在这种情况下,可以省略最后一个包含语句,因为所需的结果已经在 _matchingData 属性中。

    关于 distict() 语句的注意事项:

    由于此函数将创建一个 INNER JOIN,您可能需要考虑 在查找查询上调用 distinct 因为如果出现重复行,您可能会得到重复的行 您的条件尚未过滤它们

    http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#filtering-by-associated-data

    【讨论】:

    • 是的,不需要最后一个包含 - 所有数据都已经在 match() 函数的 _matchingData 中。我更大的问题是如何正确“展平”结果。当我这样 select() 时,它会将 url 作为键“_matchingData”下的子对象提供给我,我希望它与其他值处于同一级别。我作为解决方法所做的是 json_encode -> 删除所有“_matchingData”。字符串出现 -> json_decode.
    • distinct声明的评论很有帮助。
    猜你喜欢
    • 2016-01-05
    • 2017-12-07
    • 1970-01-01
    • 1970-01-01
    • 2011-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多