使用关联模型的链式调用时-有无括号的区别

1、问题:在模型关联中常常会疑惑例如:$user->addresses() 和 $user->addresses 的区别.

2、归纳与总结:

模型:(一对多)一个用户多个收货地址

// 用户
class User 
{
        public function addresses()
        {
            return $this->hasMany(UserAddress::class);
        }
}
// 收货地址
class UserAddress 
{
        public function user()
        {
            return $this->belongsTo(User::class);
        }
}
  • 问题: 下面$what1 和 $what2 的区别
    $user = App\Models\User::find(1) //App\Models\User
    $what1 = $user->addresses()  // Illuminate\Database\Eloquent\Relations\HasMany
    $what2 = $user->addresses    // Illuminate\Database\Eloquent\Collection
    要知道上述用法的区别, 就要认识上述的三个类:
  1. App\Models\User
    这个就是常见的模型类,假如我们要访问用户的名称就可以通用 $user->name 这样访问属性的方式来简单访问. 因为name这个这个$user实例的一个属性
  2. Illuminate\Database\Eloquent\Relations\HasMany
    看名称我们就知道,这是个Eloquent中处理一对多的类;查看源码(下图)可以看到,HasMany最终是实现了抽象父类Relation,
    而Relation 返回的是一个 叫做 Builder 的实例。 Builder(构造器) 可以简单的理解为,帮你组装sql的一个工具类。

使用关联模型的链式调用时有无括号的区别

使用关联模型的链式调用时有无括号的区别

使用关联模型的链式调用时有无括号的区别
所以对于$user->addresses()只是一个构造器。这个构造器并不能直接的帮我们获取到“用户所有的收货地址”的数据。
所以我们可以进行以下操作获取数据:

$user_addresses = $user->addresses()->get(); //获取用户所有的收货地址  Illuminate\Database\Eloquent\Collection
$user_address   = $user->addresses()->find(1); //获取该用户下id=1的收货地址 App\Models\UserAddresses

3.Illuminate\Database\Eloquent\Collection
这个就可以当作是一个“数组”, 是Larvel给我们封装好很多方法的数组对象。 里面存在一个items属性,该属性里面包含了上述的模型实例(ps:所以一般返回的“模板参数”里面都是Model实例和Collection实例。)

使用关联模型的链式调用时有无括号的区别
所以我们可以通过以下操作来获取数据:

$user_addresses  = $user->addresses //获取用户下所有的收货地址 
$user_addresses2 = $user->addresses()->get() // 和上面异曲同工
  • 复习与延申思考
    从收货地址角度出发,我们再看一看下列每个变量是什么类型的数据。
    $user_address =  App\Models\UserAddress::find(1);
    $data1 = $user_address->user();
    $data2 = $user_address->user;
    $data3 = $user_address->user()->get();
    $data4 = $user_address->user()->get()->find(1);
    $data5 = $user_address->user()->get()->find(1)->name;
    $data6 = $user_address->user()->first();
    $data7 = $user_address->user()->first()->name;
    $data8 = $user_address->user->name;




    答案
$user_address // App\Models\UserAddress;
$data1 // Illuminate\Database\Eloquent\Relations\BelongsTo;
$data2 // App\Models\User;
$data3 // Illuminate\Database\Eloquent\Collection 即使items只有一个模型;
$data4 // 如果用户的id为1时--App\Models\User;  不为1时--null
$data5 // 如果用户的id为1时--显示用户的名称即name属性; 不为1时系统报错。
$data6 // App\Models\User;
$data7 // 参照$data5
$data8 // 参照$data5
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 2

总结得不错

3年前 评论

$user->addresses 调用了 __get 魔术方法 :+1:

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!