【问题标题】:Querying entities with nested many to many relations查询具有嵌套多对多关系的实体
【发布时间】:2015-08-26 15:18:29
【问题描述】:

自从我开始使用 Laravel 以来,我就遇到了这个问题。当我想拥有一个没有特定嵌套关系的实体时,在我的一生和无数小时中,我无法通过 eloquent has() 方法获得它。我通常通过 Fluent 和左连接来做到这一点。

假设有三个模型,其中一个轴 (user_persona) 只携带相关模型的 ID;

示例

| User    |       | Persona    |       | Category    |
-----------       --------------       ---------------
| user_id | -M-M- | persona_id | -O-M- | category_id |
-----------       --------------       | persona_id  |
                                       ---------------

关系

用户

function personas()
{
    return $this->belongsToMany('Persona', 'user_persona', 'user_id', 'persona_id');
}

角色

function categories()
{
    return $this->hasMany('Category', 'persona_id');
}

问题

现在可以通过以下方式获得具有特定类别角色的用户:

User::has('personas.categories', '>=', 1, 'and', function ($q) use ($cid) {
    $q->where('category.category_id', '=', $cid)
})->first();

但我无法获取与同一类别没有这种关系的所有其他用户;

User::has('personas.categories', '=', 0, 'and', function ($q) use ($cid) {
    $q->where('category.category_id', '=', $cid)
})->get();

Eloquent 将返回用户,包括所有与角色有任何其他关系的用户。那些匹配排除关系但也有另一个不匹配的关系的用户也将被包括在内。只有那些使其所有相关角色都符合条件的才会被过滤。

Fluent 中的预期相似查询

总而言之,我希望它返回与以下查询相同的结果:

SELECT
    user.*
FROM
    user u
LEFT JOIN user_persona up ON u.user_id = up.user_id AND up.persona_id IN 
        (SELECT persona_id FROM persona_category WHERE category_id = ?)
WHERE
    up.persona_id IS NULL;

当前 Eloquent 生成的查询

SELECT
    COUNT(*)
FROM
    `user`
WHERE
    (
        SELECT
            count(*)
        FROM
            `persona`
        INNER JOIN `user_persona` ON `persona`.`persona_id` = `user_persona`.`persona_id`
        WHERE
            `user_persona`.`user_id` = `user`.`user_id`
        AND (
            SELECT
                count(*)
            FROM
                `persona_category`
            WHERE
                `persona_category`.`persona_id` = `persona`.`persona_id`
            AND `persona_category`.`category_id` = ?
        ) = ?
    ) >= ?

【问题讨论】:

    标签: laravel-4 eloquent


    【解决方案1】:

    我认为你没有使用 Laravel Eloquent ORM 关系 尝试这个 在用户模型中

    public function personas()
    {
        return $this->belongsToMany('Persona','user_persona');
    }
    

    在角色模型中

    public function users()
    {
        return $this->belongsToMany('User','user_persona');
    }
    public function categories()
    {
        return $this->hasMany('Category','user_persona');
    }
    

    在类别模型中

    public function users()
    {
        return $this->belongsToMany('User','user_persona');
    }
    public function personas()
    {
        return $this->hasOne('Persona','user_persona');
    }
    

    现在你可以像下面这样使用它了

    $user->personas->categories
      //or
    $personas->users-categories
      //or
    $personas->categories
      //or
    $category->users
      //or
    $category->personas
      //or
    $category->personas->users
      // and many other relationship queries by Eloquent
    

    并且通过热切加载,您可以避免n+1查询问题

    $user=User::with('persona')->find(1)->get();
    

    现在它将返回用户及其关系详细信息和数据或角色..

    您可以参考here - Eloquent Relationships和Eloquent Eager Loading

    【讨论】:

    • 不,我正在使用它们,我只是在这里没有提到它们。我会添加它们,但这更像是一个问题,它甚至可能还是我没有得到它的问题。
    • 当我收到你的问题时,这些关系很容易让你所做的事情成为可能。您不必查询 usign Model::has 或类似的东西..
    • 我在模型中有相同的关系。但是你提出的不是更贵吗?
    • 我有超过 10 万用户要处理
    • 如果是这样,那么您可以使用 laravel 的即时加载,例如 User::with('persona')->find(1)->get(); .. . 参考这里 laravel.com/docs/4.2/eloquent#eager-loading
    猜你喜欢
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多