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

假设有三张表

模型 主键 其余字段
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 运行生命周期解析

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 4

:+1:

2个月前

666

2个月前
Hanson

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

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

2个月前
XiaohuiLam

@Hanson :unamused:

2个月前

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!