从Laravel雄辩的资源集合中隐藏属性关系

时间:2019-05-07 17:03:22

标签: php laravel eloquent

我正在尝试构建API资源,我想在集合中隐藏关系属性。

例如,我只想在RoleCollection中隐藏属性“权限”。我的意思是我只想隐藏此属性而不是资源。因为Collection是从Resource调用的,但是我不想将其隐藏在Resource中。

Role.php

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class Role extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'created_at' => $this->created_at->format('Y-m-d H:i:s'),
            'updated_at' => $this->updated_at->format('Y-m-d H:i:s'),
            'permissions' => Permission::collection($this->permissions),
        ];
    }
}

RoleCollection.php

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class RoleCollection extends ResourceCollection
{
    public function toArray($request)
    {
        return parent::toArray($request);
    }
}

RoleController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use Spatie\Permission\Models\Role;
use App\Http\Resources\Role as RoleResource;
use App\Http\Resources\RoleCollection;

class RoleController extends Controller
{
    public function index()
    {
        $resource = Role::paginate();    
        return new RoleCollection($resource);
    }

    public function show($id)
    {
        $resource = Role::with('permissions')->find($id);    
        return new RoleResource($resource);
    }
}

响应来自:api / role / 1

{
    "data": {
        "id": 1,
        "name": "Super Administrador",
        "created_at": "2019-05-07 16:45:38",
        "updated_at": "2019-05-07 16:45:38",
        "permissions": [
            {
                "id": 1,
                "name": "user.list"
            },
            {
                "id": 2,
                "name": "user.view"
            },
            {
                "id": 3,
                "name": "user.save"
            },
            {
                "id": 4,
                "name": "user.delete"
            }
        ]
    }
}

来自:/ api / roles

的回复
{
    "data": [
        {
            "id": 1,
            "name": "Super Administrador",
            "created_at": "2019-05-07 16:45:38",
            "updated_at": "2019-05-07 16:45:38",
            "permissions": [
                {
                    "id": 1,
                    "name": "user.list"
                },
                {
                    "id": 2,
                    "name": "user.view"
                },
                {
                    "id": 3,
                    "name": "user.save"
                },
                {
                    "id": 4,
                    "name": "user.delete"
                }
            ]
        },
        {
            "id": 2,
            "name": "Administrador",
            "created_at": "2019-05-07 16:45:38",
            "updated_at": "2019-05-07 16:45:38",
            "permissions": []
        }
    ],
    "links": {
        "first": "http://127.0.0.1:32773/api/roles?page=1",
        "last": "http://127.0.0.1:32773/api/roles?page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "http://127.0.0.1:32773/api/roles",
        "per_page": 15,
        "to": 2,
        "total": 2
    }
}

2 个答案:

答案 0 :(得分:1)

执行此操作的一种方法是使用whenLoaded方法。当尚未加载关系时,whenLoaded将返回一个MissingValue实例。 Laravel反过来会从您的共振中排除此属性。

它不仅对于隐藏某些响应中的属性很有用,而且还有助于提高性能。当前,当未加载此关系时,您的资源将对每个Permission进行查询,以获取Role个模型。

您的资源可能如下:

return [
    ...
    'permissions' => Permission::collection($this->whenLoaded('permissions')),
];

Laravel docs

答案 1 :(得分:0)

处理这些问题的最好方法之一就是使用Fractals

您可以为所有模型定义一个Transformer类,在每次调用它们时都处理是否包含关系,还可以定义要显示或隐藏的属性。

基本上,只有一个点可以在JSON中序列化模型,并将所有逻辑放在这里。

您还可以通过单个模型转换器对整个集合进行JSON化,非常方便!