Laravel 5.5 Api Resource
打赏作者

zhangwei

实际项目构建api中这个resource 放在哪一层呢 感觉主要做响应转化的话 放控制器与仓库之间比较合理吧

zhangwei

俺能想到的就是在仓库依次注入resource resoureceCollection 和model 在仓库里直接对model 数据转化与过滤

JellyBool 回复 zhangwei

其实 laravel 默认这种已经不错了

sodasix

教主真是效率 ,

jayin

可以,自定义键方便一点,但是控制字段,不如select,get方便

JellyBool 回复 jayin

这个其实更数据库是没有什么关系的

waicmy

Jelly,我这里还有个问题,但不知道改如何解答! https://iluoy.com/articles/gZYbRjYE 求解答呢…

JellyBool 回复 waicmy

其实这些null值是我没有查询出来的字段

这是什么

waicmy 回复 JellyBool

就是我在with的时候并没有select这些字段,最后transform出来就是null了

JellyBool 回复 waicmy

那你不返回这些字段呗

waicmy 回复 JellyBool

但是…我的toArray不只是单单针对某次的返回啊…我每次查询的字段都是不一样的…所以我的toArray里面所有的字段都做了映射…但是查询的时候.并不是每次都是查询出全部字段的,当查询出来的字段toArray有结果中没有的时候,就会出现null…

JellyBool 回复 waicmy

那你再生成新的 Resource 就好

盆盆盆盆盆盆

使用5.5还有必要使用jwt+dingo吗?如何完成多用户认证api呢?

JellyBool 回复 盆盆盆盆盆盆

我会使用 passport 。不用 dingo 了

Nixus 回复 盆盆盆盆盆盆

你说的是多用户认证还是多表认证?

高永立

错误信息是不是就要自己写了。

JellyBool 回复 高永立

嗯,这个完全可以自己做的

Nixus 回复 高永立

错误信息要怎么写?没啥思路

Nixus

老师,希望这节课能够加点深度,视频中的内容在 API Resource 的文档中都有,感觉就是对文档的一个演示;
如果一个模型,有多种不同的数据集合返回,错误信息的返回,这个该怎么来实现?没思路

JellyBool 回复 Nixus

应该可以,理论上这个跟 API 那个系列差不多。但是我得先实践试试先

Nixus 回复 JellyBool

谢谢老师!您是最棒的!

尼好再见

我现在遇到这样的问题了,比如一个User的数据我要返回多种不同的 API 结果,那么我要怎么做呢,创建多个 resoureceCollection 吗?

JellyBool 回复 尼好再见

比如一个User的数据我要返回多种不同的 API 结果

这是什么?具体一点?

尼好再见 回复 JellyBool

具体讲就是,我现在有一个用户表,然后我第一个api 接口返回的是这个用户的(昵称 +电话)其他不需要;第二个接口我需要返回用户的(电话+真实姓名+身份证号码+ 银行卡信息)其中 银行卡信息存在另外一个银行卡表;第三个接口我需要返回用户的(姓名+电话+注册时间+余额+积分+默认地址)其中默认地址是在地址表。就这么三个接口我需要怎么操作?

Nixus 回复 尼好再见

这个问题也是困惑我好久的,现在又回到laravel的这个项目上了,也就又回到了这个问题上
查了很多,都没找到涉及该问题的内容

Nixus 回复 尼好再见

在生成的Resource文件的时候,toArray方法中,默认有一行代码:

$data = parent::toArray($request);
foreach($data as $key => &$value) {
     $key = $this->fieldsMap($key);
}
return [
      'code'=>200,
      'data' => $data
];

这行代码,拿到的就是查询结果的数据,而且是可变的

如果需要把每个字段的名字都换成其他的话,可能还需要定义一个方法:

public function fieldsMap($key)
{
    $fields = [
        'mobile'   => 'phone',
        'username' => 'name',
    ];

    return isset($fields[$key]) ? $fields[$key] : $key;
}

或许可以这样实现

尼好再见 回复 Nixus

这个和直接 return 没什么区别啊!问题还是存在的,还是需要创建多个 resourece

Nixus 回复 尼好再见

有区别的,完全可以解决掉创建多个API Resource的问题

尼好再见 回复 JellyBool

难道创建 三个 resoureceCollection + 三个 resourece ?

JellyBool 回复 尼好再见

不想创建这么多的话,就条件判断呗

Nixus 回复 JellyBool

老师,请问,加判断是加在哪儿?是Controller还是Resource中?
感觉这个Api Resource有点儿鸡肋,不够灵活

JellyBool 回复 Nixus

比较普通的 Api 是可以解决

foxriver123 回复 JellyBool

web.php

Route::group(['prefix'=> 'api'],function(){
	Route::get('/user/{id}/{method}', function ($id) {
		$user = App\User::find($id);
	    return new App\Http\Resources\User($user);
	});
	Route::get('/users/{method}',function(){
		$users = App\User::all();
		return new App\Http\Resources\UserCollection($users);
	});
});

User.php

class User extends Resource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    private $status = 'success';
    private $code = 200;
    public function toArray($request)
    {
        if(method_exists($this, $request->method) && $method = $request->method){
            return $this->$method();
        }
        $this->status = 'failed';
        $this->code = '404';
    }
    public function getUser(){
        return [
            'username' => $this->name,
        ];
    }

    public function getUserEmail(){
        return [
            'username' => $this->email,
        ];
    }

    public function with($request){
        return [
            'status' => $this->status,
            'code'   => $this->code,
        ];
    }

}

UserCollection.php

class UserCollection extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    private $status = 'success';
    private $code = 200;
    public function toArray($request)
    {
        if(!method_exists(User::class, $request->method)){
            $this->status = 'urlNotFound';
            $this->code = '404';
            return [];
        }
        return parent::toArray($request);
    }

    public function with($request){
        return [
            'status' => $this->status,
            'code'   => $this->code,
        ];
    }
}

这个应该可以解决问题

尼好再见 回复 foxriver123

用是怎么用的

foxriver123 回复 尼好再见

如果你想拿用户id为1的用户名信息就用 api/user/1/getUser ,如果你想拿用户id为1的邮箱信息就用 api/user/1/getEmail,当然你可以在geiUser或者getEmail里面加入更多你想返回的属性,然后你也可以根据你的需求自定义更多类似于getUser getEmal的方法

尼好再见 回复 foxriver123

一脸懵逼!这个写了可以不用写路由直接用吗?正常的 Resource 像官方文档里那样不是需要 new User($users); 这个样子吗?

foxriver123 回复 尼好再见

你看下最上面的web.php里面,不是写的有吗

尼好再见 回复 foxriver123

我还有个问题,现在是用 Eloquent ORM 查询出的数据可以生成 API,但是在现实生产环境中往往会出现不同的情况,比如对查询的数据需要重构,可能需要加入一些额外字段,比如我返回User表信息的同时,我需要从我的配置表中查询出某两个字段的值一起返回,但是配置表和User表没有直接关系,还有我有时候需要从 redis 里获取数据,增加到某个查询的结果中,这种情况下我对数组的重构是在 Resource 中进行还是在外面!

尼好再见 回复 foxriver123

Resource 里有个with 我想有没有办法把数据传递个 with 这样就可以 附加其他额外信息了!

尼好再见 回复 JellyBool

Jelly 我觉的这个 Laravel 5.5 Api Resource 确实可以再讲的深入点!

foxriver123

这是多么2的问题!当我没问哈哈!!!!

foxriver123

为什么我的代码贴出来是这个形状。。

JellyBool 回复 foxriver123

使用 markdown 格式排版一下

foxriver123 回复 JellyBool

恩,好的。先学习下markdown = =

Nixus

@JellyBool 老师,新年快乐!
又看了一遍视频,感觉API Resource如果只是改变一下数据格式,完全没有存在的价值,还不如封装一个通用的方法来的方便呢
您觉得,API Resource存在的意义是什么?

JellyBool 回复 Nixus

他就是改格式的,就是 Transformer 这一层。

Nixus

又看了一遍视频,有两个问题,希望老师有空可以解答一下:
1、返回数据的排序问题:

{
     "data": {},
     "status": "success"
}

一般情况下,都是状态码和状态信息会放在返回数据的最开始,比如这样:

{
     "status": "success",
     "data": {}
}

但是使用with的时候,这类信息基本上都是放在了 data 的后面,有没有办法实现这种排序呢?
2、collection中的分页信息如何调整?

  • 一般API开发中,基本上都不需要链接,所以想把links删掉,尝试了很多方法,都没办法实现;
  • meta中的信息,其实只需要其中的三四个字段,怎么删除不需要的信息?

老师,有空帮忙看下这个问题,谢谢

JellyBool 回复 Nixus
{
     "data": {},
     "status": "success"
}

这个只是根据首字母来排序了吧。

2.我觉得这个问题,你手动取分页的各项数据应该就好了。

https://laravel.com/docs/5.5/pagination#paginator-instance-methods
这个应该有用

Nixus 回复 JellyBool

我直接不用API Resource了,感觉用处不大,自己写了专门格式化数据的trait

JellyBool 回复 Nixus

可以,你要完全自己定制的话,自己写 Transformer 层呗