Laravel:具有嵌套自我关系的资源



我有一个Category资源,如下所示:

<?php
namespace DomainCategoryResources;
use IlluminateHttpRequest;
use IlluminateHttpResourcesJsonJsonResource;
class CategoriesResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param  Request  $request
* @return array
*/
public function toArray($request): array
{
return [
'id' => (string)$this->id,
'type' => 'categories',
'attributes' => [
'name' => $this->name,
'slug' => $this->slug,
'parent' => $this->parent,
'description' => $this->description,
'image' => $this->image,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
]
];
}
}

parent是类别的父级的ID,它本身就是Category。当我调用返回此资源的端点时,我得到:

{
"data": {
"id": "5",
"type": "categories",
"attributes": {
"name": "Paper",
"slug": "paper",
"parent": 1,
"description": "test",
"image": null,
"created_at": "2022-09-09T19:01:44.000000Z",
"updated_at": "2022-09-09T19:01:44.000000Z"
}
}
}

这正是我所期望的。但现在我认为返回嵌套关系会更好,所以我不想返回上面的内容:

{
"data": {
"id": "5",
"type": "categories",
"attributes": {
"name": "Paper",
"slug": "paper",
"parent": {
"id": "5",
"type": "categories",
"attributes": {
"name": "Parent Paper",
"slug": "parent-paper",
"parent": 0,
"description": "test 2",
"image": "test.png",
"created_at": "2022-09-09T19:01:44.000000Z",
"updated_at": "2022-09-09T19:01:44.000000Z"
},
"description": "test",
"image": null,
"created_at": "2022-09-09T19:01:44.000000Z",
"updated_at": "2022-09-09T19:01:44.000000Z"
}
}
}

所以我考虑在模型中添加关系:

<?php
namespace DomainCategoryModels;
use DomainProductModelsProduct;
use DomainSharedBaseModel;
use IlluminateDatabaseEloquentRelationsHasMany;
use IlluminateDatabaseEloquentRelationsHasOne;
use IlluminateSupportStr;
class Category extends BaseModel
{
protected $fillable = [
'name',
'parent',
'description',
'image',
];
public function parent() : BelongsTo
{
return $this->belongsTo(Category::class, 'parent');
}
}

然后更新resource:中的parent字段

public function toArray($request): array
{
return [
'id' => (string)$this->id,
'type' => 'categories',
'attributes' => [
'name' => $this->name,
'slug' => $this->slug,
'parent' => new CategoriesResource($this->parent),
'description' => $this->description,
'image' => $this->image,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
]
];
}

但这不起作用。我收到一个错误,上面写着:

尝试读取属性";id";在内部

此错误指向ID字段:

public function toArray($request): array
{
return [
'id' => (string)$this->id,
``
Furthermore, I don't want it to get into a loop, meaning that when displaying the `parent` info I don't want it to display the parent's parent and so on.
Is this possible?

我在这里看到了几个问题:

为什么在HasOne关系上使用CategoryResource::集合?

而且,该父级可能嵌套,从而产生N+1问题,您应该在可能的情况下使用resources条件句:https://laravel.com/docs/9.x/eloquent-resources#conditional-关系

编辑:因此,应用此操作将防止进一步加载Category::parent关系:

public function toArray($request): array
{
return [
'id' => (string)$this->id,
'type' => 'categories',
'attributes' => [
'name' => $this->name,
'slug' => $this->slug,
'parent' => new CategoriesResource($this->whenLoaded('parent')),
'description' => $this->description,
'image' => $this->image,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
]
];
}

最新更新