LaravelAPI资源:如何返回无限嵌套的类别数组及其子类别?



我使用Laravel 6.x,下面是我的响应JSON。

{
"data": [
{
"id": 1,
"name": "quam",
"parent_id": 0
},
{
"id": 2,
"name": "quia",
"parent_id": 1
},
{
"id": 3,
"name": "beatae",
"parent_id": 1
},
{
"id": 4,
"name": "aut",
"parent_id": 2
},
{
"id": 5,
"name": "provident",
"parent_id": 0
},
{
"id": 6,
"name": "voluptate",
"parent_id": 0
},
{
"id": 7,
"name": "vel",
"parent_id": 2
},
{
"id": 8,
"name": "sed",
"parent_id": 3
},
{
"id": 9,
"name": "voluptates",
"parent_id": 0
},
{
"id": 10,
"name": "adipisci",
"parent_id": 6
},
...
]
}

但它想像这样:

{
"data": [
{
"id": 1,
"name": "quam",
"children": [
{
"id": 2,
"name": "quam"
"children":[
{
"id": 4,
"name": "aut"
},
{
"id": 7,
"name": "vel",
"children": [
...
]
}
]
},
{
"id": 3,
"name": "quam",
"children":[
{
"id": 8,
"name": "sed"
}
]
},
]
},
{
"id": 5,
"name": "provident"
},
{
"id": 6,
"name": "voluptate",
"children": [
{
"id": 10,
"name": "adipisci"
}
]
},
{
"id": 9,
"name": "voluptates"
},
...
}

实际上,我想删除parent_id属性children并将数组添加到由具有此parent_id的其他对象组成的每个对象。

类别资源.php

class CategoryResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'parent_id' => $this->parent_id,
];
}
}

类别控制器.php

class CategoryController extends Controller
{
public function index()
{
return CategoryResource::collection(Category::all());
}
}

如何实现此结构?

从我所看到的,你的问题只是关系。要创建"树资源",您必须加载大量关系。

恕我直言,这不是一个好的选择,特别是如果您必须加载大量元素,但一般来说,像这样的结构可能是一个危险的瓶颈。

无论如何。。。简单的方法是急切加载,因此您必须使用此属性添加基本模型(查看官方文档(

class Parent extends Model {
// [...]
/**
* The relationships that should always be loaded.
*
* @var array
*/
protected $with = ['children'];
// [...]
public function children() {
return $this->hasMany('whatever');
}
}

接下来,您必须按如下方式更新 JSON 资源(为此,请查看有关资源关系的官方文档(。

class CategoryResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'parent_it' => $this->parent_id,
'childrend' => ChildrenResource::collection($this->whenLoaded('children')),
];
}
}

这样,由于每次请求Parent时,它都会急于加载其子级,因此资源将以递归方式映射到Child资源中,每个关系都向下映射到叶子

假设类别是一个雄辩的模型,模型可以在关系中引用自己,并且这些关系可以是递归的。


class Category extends Model
{
protected $hidden = ['parent_id'];
public function children()
{
return $this->hasMany('AppCategory', 'parent_id')->with('children');
}
}

所以现在获得你想要的结构就像

Category::with('children:id,name,parent_id')->get('id', 'name', 'parent_id');

您必须在 select 语句中包含parent_id才能使关系正常工作,但我添加到模型中的$hidden变量使parent_id无法显示在序列化结果中。这里唯一需要注意的是,所有类别都将有一个children属性,对于没有子类别的类别,该属性将为空。因此,在您的 toArray 方法中,您必须检查空的子项[] 并排除它们

首先,您需要定义一个关系,用于使用此方法检索没有父级的主类别的子项

/**
* get sub product categories of this category
*
* @return mixed
*/
public function childCategories()
{
return $this->hasMany(Category::class,'parent_id');
}

然后你需要用这个方法加载子类别的子类别:

/**
* get recursive all sub categories of this category.
*
* @return mixed
*/
public function childrenCategories()
{
return $this->hasMany(Category::class,'parent_id')->with('childCategories');
}

现在您可以使用此静态函数检索它们

/**
* get all Main categories with children.
*
* @return mixed
*/
public static function allMainCategoriesWithChildren()
{
return self::whereNull('parent_id')->with('childrenCategories')->get();
}

现在,您可以在资源中使用它或直接将其返回到控制器中

use AppCategory;
return Category::allMainCategoriesWithChildren();

最新更新