HasManyThrough 不够灵活? 猥琐发育,别浪!

假设有三张表

模型 主键 其余字段
posts id
tags id
post_tags post_id tag_id

使用 HasManyThrough 是很好给 Post 关联上的 Tag 模型的。

但如果这样的情况呢?

模型 主键 其余字段
users id
user_children user_id child_id

释义:

用户 User 模型拥有多个子模型 User ,且通过 UserChild.user_id = :用户id 查到 User.id=UserChild.child_id 的子 User

我们尝试建立两个模型

  • app\Models\User.php
<?php
namespace App\Models;

class User extends \Eloquent
{
    /**
     * 子用户
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
     */
    public function children()
    {
        return $this->hasManyThrough(User::class, UserChild::class, 'user_id', 'id', 'id');
    }
}
  • app\Models\UserChild.php
<?php
namespace App\Models;

class UserChild extends \Eloquent
{
    /**
     * 用户
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user() {
        return $this->belongsTo(User::class, 'id', 'user_id');
    }

    /**
     * 子用户
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function child() {
        return $this->hasOne(User::class, 'id', 'child_id');
    }
}

通过这种写法,我们查询的时候执行的SQL并不是我们预期的那样

select
    `users`.*,
    `user_children`.`user_id`
from
    `users`
    inner join `user_children` on `user_children`.`id` = `users`.`id` // 这里的 `user_children`.`id` 是大大的错误,因为需要通过user_children.child_id 来关联回User模型
where
    `user_children`.`user_id` = :id 
    and `users`.`deleted_at` is null

解决方法

  • app/Models/User.php 的children方法修改成
<?php
...

    /**
     * 子用户
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
     */
    public function children()
    {
        return $this->hasManyThrough(User::class, Relations\UserChildRelation::class, 'user_id', 'id', 'id');
    }
}
  • 新建 app/Models/Relations/UserChildRelation.php
<?php
namespace App\Models\Relations;

class UserChildRelation extends \App\Models\UserChild
{
    protected $primaryKey = 'child_id';
}

然后测试

select
    `users`.*,
    `user_children`.`user_id`
from
    `users`
    inner join `user_children` on `user_children`.`child_id` = `users`.`id`
where
    `user_children`.`user_id` = :id
    and `users`.`deleted_at` is null

正常!

Fine or not, never stop. Laravel 运行生命周期解析

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 4
eiomi

:+1:

6个月前

666

6个月前
Hanson

用户 User 模型拥有多个子模型 User

那么,为什么不在 User 表加个 parent_id :laughing:

6个月前
XiaohuiLam

@Hanson :unamused:

6个月前

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!