Laravel8.x API Resources处理关联数据的返回

作者: 温新

分类: 【Laravel】

阅读: 2042

时间: 2021-12-19 12:43:50

hi,我是温新,一名PHPer

在实际开发中,返回的数据有时候是很复杂的,有着较多的关联关系,那么,本篇文章贴近于实际开发进行演示,以博客为例子。

现在有了用户,还缺少文章与分类,现在新建这两个表。

CREATE TABLE `articles` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) unsigned NOT NULL,
  `category_id` int(10) unsigned NOT NULL,
  `title` varchar(100) NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `articles_user_id_index` (`user_id`),
  KEY `articles_category_id_index` (`category_id`)
);

CREATE TABLE `categories` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(80) NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
);

关于表中数据,自己去手动添加吧。

获取关联数据

第一步:明确需求

// routes/api.php

Route::get('arts', function () {
    return \App\Models\Article::all();
});

返回的数据为

[
  {
    "id": 1,
    "user_id": 1,
    "category_id": 1,
    "title": "文章1",
  }
]

在实际中,一般想要拿到用户名和分类名称,这也就需求,除了拿到这两个外,它们的信息都可以拿到。

第二步:建立关联关系

// app/Modles/User.php
// 用户可以有很多文章
public function articles()
{
    return $this->hasMany(Article::class, 'user_id', 'id');
}

// app/Modles/Article.php
// 用户与文章属于一对多关系
public function user()
{
    return $this->belongsTo(User::class, 'user_id', 'id');
}

// 文章与分类属于一对多关系
public function category()
{
    return $this->belongsTo(Category::class, 'category_id', 'id');
}

// app/Modles/Category.php
// 一个分类可以有很多文章
public function articles()
{
    return $this->hasMany(Article::class, 'category_id', 'id');
}

第三步:创建与编写resources与collection

创建

php artisan make:resource ArticleResource 
php artisan make:resource ArticleCollection

编写

//  app/Http/Resources/ArticleCollection.php
public function toArray($request)
{
    // 返回集合数据
    return [
        'data'  =>  $this->collection
    ];
}

//  app/Http/Resources/ArticleResource.php
public function toArray($request)
{
    // 集合数据进行处理
    return [
        'title'     =>  $this->title,
        // new 自身,对集合数据进行查询处理
        'author'    =>  new UserResource(User::find($this->user_id)),
        // 单条数据直接取出分类名称
        'category'  =>  Category::find($this->category_id)->name,
    ];
}

第四步:修改路由文件

// routes/api.php
Route::get('arts', function () {
    $arts = \App\Models\Article::all();
    return new \App\Http\Resources\ArticleCollection($arts);
});

第五步:改写UserResource.php

注意:由于这一步我是延续之前文章进行使用的,因此需要对其进行改写,不然会报错。

在这里也可以控制用户数据的返回。

//  app/Http/Resources/UserResource.php 
public function toArray($request)
{
    return [
        'id'        =>  $this->id,
        'username'  =>  $this->name,
        'email'     =>  $this->email,
    ];
}

第六步:访问路由获取数据

{
  "data": [
    {
      "title": "文章1",
      "author": {
        "id": 1,
        "username": "lisi",
        "email": "111@qq.com"
      },
      "category": "PHP"
    },
  ]
}

对数据权限进行控制

简单的例子,有些字段是管理员可以看到,或者管理员可以看到所有信息。

演示管理管理员可以看到的字段。

//  app/Http/Resources/UserResource.php 

public function toArray($request)
{
    // 如果是管理员登录
    $admin = true;

    return [
        'id'        =>  $this->id,
        'username'  =>  $this->name,
        'email'     =>  $this->email,
        
        $this->mergeWhen($admin, [
            // 管理员登录才能看到这两个字段
            'created_at'    =>  $this->created_at,
            'is_admin'      =>  '管理员才能看到的字段'
        ]),
    ];
}

用户下的所有文章

修改UserResource.php

//  app/Http/Resources/UserResource.php 
public function toArray($request)
{
    return [
        'id'        =>  $this->id,
        'username'  =>  $this->name,
        'email'     =>  $this->email,
        'arts'  =>  $this->articles,
    ];
}

定义路由

// routes/api.php

Route::get('/users/{id}', function (\App\Models\User $user, $id) {
    $users = \App\Models\User::where('id',$id)->get();
    return new \App\Http\Resources\UserCollection($users);
});

我是温新

每天进步一点点,就一点

请登录后再评论