使用关联模型的链式调用时-有无括号的区别
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
- App\Models\User
这个就是常见的模型类,假如我们要访问用户的名称就可以通用 $user->name 这样访问属性的方式来简单访问. 因为name这个这个$user实例的一个属性 - 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 协议》,转载必须注明作者和本文链接
总结得不错
$user->addresses
调用了 __get 魔术方法 :+1: