首页 > 解决方案 > 解析 api 资源中的 n+1

问题描述

我写这个问题是因为我找不到获得预期结果的方法。

我有 3 个模型:

 1- User
 2- Role
 3- Permission
  1. 一个用户可以关联多个角色,因此用户和角色之间存在多对多的关系。
  2. 一个用户可以有多个直接关联的权限,所以用户和权限之间是多对多的关系。
  3. 一个角色可以有多个与之关联的权限,因此角色和权限之间存在多对多的关系。

我有 3 个具有以下结构的 api 资源:

 1- UserResource
 2- RoleResource
 3- PermissionResource

应用程序/Http/Resources/UserResource.php

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'roles' => RoleResource::collection($this->whenLoaded('roles')),
            'permissions' => PermissionResource::collection($this->whenLoaded('permissions', $this->getInheritPermissions())),
        ];
    }
}

应用程序/Http/Resources/UserResource.php

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class RoleResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'guard' => $this->guard,
            'description' => $this->description,
            'permissions' => PermissionResource::collection($this->whenLoaded('permissions'))
        ];
    }
}

应用程序/Http/Resources/PermissionResource.php

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class PermissionResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'roles' => RoleResource::collection($this->whenLoaded('roles'))
        ];
    }
}

在我的控制器中,我试图UserResource用某个用户的数据返回资源,如下所示:

<?php

namespace App\Http\Controllers;

use App\Http\Resources\UserResource;
use App\Models\User;

class HomeController extends Controller
{
    public function index()
    {
         return UserResource::collection(User::with(['roles', 'permissions'])->get());
    }
}

我得到以下回应:

在此处输入图像描述

如果您查看roles密钥,则permissions关系也已加载,这是我不想要的,因为在控制器中我只加载rolespermissions关系。如果控制器按如下方式加载关系,这个答案会很好:

    public function index()
    {
         return UserResource::collection(User::with(['roles.permissions', 'permissions'])->get());
    }

好吧,我想这个问题已经给出,因为在User模型中,我有一个名为 的方法getInheritPermissions(),它获取用户从与其关联的角色继承的所有权限。

public function getInheritPermissions()
    {
        return $this->loadMissing('roles.permissions')->getAttribute('roles')->flatMap(function ($role) {
            return $role->permissions;
        });
    }

这样,只获取用户拥有的角色权限的查询是非常高效的。但是在 API 资源中,它并没有像我预期的那样显示结果。我还了解到,在资源 API 中,我无法验证是否加载了嵌套关系。就像是:

'permissions' => PermissionResource::collection($this->whenLoaded('roles.permissions'))

我该如何控制这种情况,因为我需要使用 loadMissing 方法来加载用户从他们的角色中获得的权限。

非常感谢您提前。

标签: laraveleloquentlaravel-api

解决方案


推荐阅读