对于开发过thinkphp的开发者来说,对访问器(获取器)和关联模型都不默认。他们都是属于在Model类中定义数据,在获取的时候进行调用。下面分别是访问器和关联模型的使用。

一、定义与使用

1.1 访问器

  • 定义

    1. class User extends Model
    2. {
    3. /**
    4. * 获取用户的姓名.
    5. *
    6. * @param string $value
    7. * @return string
    8. */
    9. public function getFirstNameAttribute($value)
    10. {
    11. return ucfirst($value);
    12. }
    13. }
  • 使用
    直接使用,这样使用在需要first_name才会去执行具体getFirstNameAttribute方法的代码。 ```php $user = App\User::find(1);

$firstName = $user->first_name;

  1. 预加载 append,这样在`Model`被实例化的时候就会执行 `getFirstNameAttribute` 方法。如果是所有实例化对象都需要,可以直接在`Model` `$appends`属性中定义,这样所有Model实例化对象都会预加载appends的访问器。
  2. ```php
  3. $user = App\User::find(1)->append('first_name');
  4. $firstName = $user->first_name;

1.2 关联模型

  • 定义

    1. class User extends Model
    2. {
    3. public function role()
    4. {
    5. return $this->hasOne(Role::class, 'user_id', 'id');
    6. }
    7. }
  • 使用

直接访问,只要Model中有定义,在Model对象就通过直接访问属性获取数据。但是需要注意点,是只有访问的时候才会去执行定义的方法,如果你这次请求中没有需要获取就不会调用。

  1. $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;
}

image.png

二、访问器与模型关联结合

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 访问器与模型关联结合

  1. 定义模型关联

    
     public function role(): HasOne
     {
         return $this->hasOne(AdminRole::class, 'role_id', 'role_id');
     }
    
  2. 访问器从模型关联中获取数据

     public function getRoleNameAttribute(): string
     {
         if ($this->role_id === 0) {
             return "系统管理员";
         }
    
         return $this->role && $this->role->role_name ? $this->role->role_name : '';
     }
    
  3. 预加载批量获取数据,记住需要加入 ->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');
    }));