对于开发过thinkphp的开发者来说,对访问器(获取器)和关联模型都不默认。他们都是属于在Model类中定义数据,在获取的时候进行调用。下面分别是访问器和关联模型的使用。
一、定义与使用
1.1 访问器
定义
class User extends Model
{
/**
* 获取用户的姓名.
*
* @param string $value
* @return string
*/
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
}
使用
直接使用,这样使用在需要first_name
才会去执行具体getFirstNameAttribute
方法的代码。 ```php $user = App\User::find(1);
$firstName = $user->first_name;
预加载 append,这样在`Model`被实例化的时候就会执行 `getFirstNameAttribute` 方法。如果是所有实例化对象都需要,可以直接在`Model` 的`$appends`属性中定义,这样所有Model实例化对象都会预加载appends的访问器。
```php
$user = App\User::find(1)->append('first_name');
$firstName = $user->first_name;
1.2 关联模型
定义
class User extends Model
{
public function role()
{
return $this->hasOne(Role::class, 'user_id', 'id');
}
}
使用
直接访问,只要Model中有定义,在Model对象就通过直接访问属性获取数据。但是需要注意点,是只有访问的时候才会去执行定义的方法,如果你这次请求中没有需要获取就不会调用。
$role = User::query()->find(1)->role;
预加载:对于批量获取(get)多个数据,如果通过直接访问,会在遍历每一个Model的时候都去执行定义的方法,这样会增加查询次数。使用预加载就会在批量查询的时候只需要查询一次关联模型就可以。
//预加载,只查询一次role表
$users = User::query()->with('role')->get();
foreach ($users as $user){
echo $user->role->name;
}
//这会多次查询role表
$users = User::query()->get();
foreach ($users as $user){
echo $user->role->name;
}
二、访问器与模型关联结合
2.1 需求
我们经常会有这样的一个需求,我们在查找管理员列表的时候,我们需要显示每个管理员角色的名称,而我们管理员的表一般都只会存有role_id,如果需要管理员的中文名就需要遍历每个管理员,然后再去查找对应role_id的中文名称。
我们想要的是
{
"user_id":123,
"user_name:"管理员1",
"role_name":"角色1"
}
{
"user_id":123,
"user_name:"管理员1",
"role":{
"role_id":123,
"role_name":"角色1"
}
}
2.2 传统解决方法
- 遍历请求数据库 ```php $users = User::query()->get();
foreach ($users as $user){ echo $user->role_name= Role::where(‘role_id’,$user_role_id)->value(‘role_name’); }
- 访问器
```php
$users = User::query()->with('role')->get();
foreach ($users as $user){
echo $user->role->name;
}
2.3 访问器与模型关联结合
定义模型关联
public function role(): HasOne { return $this->hasOne(AdminRole::class, 'role_id', 'role_id'); }
访问器从模型关联中获取数据
public function getRoleNameAttribute(): string { if ($this->role_id === 0) { return "系统管理员"; } return $this->role && $this->role->role_name ? $this->role->role_name : ''; }
预加载批量获取数据,记住需要加入
->with('role')
,否则或多次请求数据库 ```php AdminUser::where($where)->with(‘role’) //->makeHidden([‘role’]) // 如果你不希望把所有role数据展示,还可以申明隐藏 ->each(function (Model $q) { //动态遍历append获取需要的role_name,也可以在Model定义appends $q->append(‘role_name’); })
4. 分页 paginate 相关操作
```php
$lists = AdminUser::where($where)
->with('role')
->orderBy('created_at', 'DESC')
->paginate();
//执行分页操作后,对获取的数据Collection遍历执行动态操作后再写回去
$lists->setCollection($lists->getCollection()
->makeHidden(['role']) //隐藏其他role信息
->each(function (Model $q) {
$q->append('role_name');
}));