【发布时间】:2020-04-30 21:53:49
【问题描述】:
在 Laravel 6 后端 rest api 应用程序中,我使用 ResourceCollection 和 Resourcem 定义,例如:
<?php
namespace App\Http\Resources;
use App\Facades\MyFuncsClass;
use Illuminate\Http\Resources\Json\ResourceCollection;
class TaskCollection extends ResourceCollection
{
public function toArray($task)
{
return [
$this->collection->transform(function($task){
return [
'id' => $task->id,
'name' => $task->name,
'slug' => $task->slug,
...
'events' => !empty($task->events) ? $task->events : [],
'events_count' => !empty($task->events_count) ? $task->events_count : 0,
'created_at' => $task->created_at,
'updated_at' => $task->updated_at,
];
}),
];
}
public function with($task)
{
return [
'meta' => [
'version'=>MyFuncsClass::getAppVersion()
]
];
}
}
我发现这个决定是在 Laravel 5.5 API resources for collections (standalone data)
它对我有用,但我不喜欢我在客户端部分获取数据的方式,因此对于控件中定义的数据列表:
return (new TaskCollection($tasks));
我必须在 vue/cli app 中编写:
axios.post(this.apiUrl + '/adminarea/tasks-filter', filters, this.credentialsConfig)
.then((response) => {
this.tasks = response.data.data[0]
this.tasks_total_count = response.data.meta.total
this.tasks_per_page = response.data.meta.per_page
当我需要获得我在 laravel 控件中定义的 1 个项目时:
return (new TaskCollection([$task])); // I have to wrap it as array
我必须在 vue/cli app 中编写:
axios.get(this.apiUrl + '/adminarea/tasks/' + this.task_id, this.credentialsConfig)
.then((response) => {
// console.log('response::')
// console.log(response)
//
this.taskRow = response.data.data[0][0]
我不喜欢 data.data[0] 和 data.data[0][0] 之类的语法,甚至对我有用
在我的 app/Providers/AppServiceProvider.php 我有几行:
<?php
namespace App\Providers;
use Auth;
use Validator;
use Illuminate\Http\Resources\Json\Resource;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Resource::withoutWrapping(); // looks like that does not work for ResourceCollection!
<?php
namespace App\Providers;
use Auth;
use Validator;
use Illuminate\Http\Resources\Json\Resource;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Resource::withoutWrapping();
...
如果有办法摆脱 vue/cli 部分中的 data.data[0] 和 data.data[0][0] ?
修改 2: 我创建了几个列的新资源 app/Http/Resources/Skill.php :
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class Skill extends JsonResource
{
public static $wrap = 'skills';
public function toArray($request)
{
return [
'id' => $request->id,
'name' => $request->name,
'user_id' => $request->user_id,
'user_name' => $request->user_name,
'skill_id' => $request->skill_id,
'skill_name' => $request->skill_name,
'rating' => $request->rating,
'created_at' => $request->created_at,
];
}
}
和 app/Http/Resources/SkillCollection.php :
<?php
namespace App\Http\Resources;
use App\Facades\MyFuncsClass;
use App\Http\Resources\Skill;
use Illuminate\Http\Resources\Json\ResourceCollection;
class SkillCollection extends ResourceCollection
{
public static $wrap = 'skills';
public function toArray($request)
{
return $this->collection->transform(function($request){
parent::toArray($request);
});
}
结果我有空的“技能”:[null,null,null,null] 结果。怎么了?
谢谢!
【问题讨论】:
-
您定义
ResourceCollection而不使用类来返回单一资源是否有原因,例如定义TaskResource扩展JsonResource然后返回TaskResource::collection($tasks)? -
我认为无论您使用
withoutWrapping(),您的资源都被包装在data中,因为您的meta函数返回一个非空对象。如果您有with数据,请在此处查看 source code,Laravel 会在其中包装您的回复。 -
一开始我尝试了 JsonResource,但是由于我需要方法 public function with($task) ... 就像在我的代码中一样,我尝试了它,但它对我不起作用。我发现 JsonResource 无法访问这个“with”方法,而只能访问 ResourceCollection。是这样吗?
-
我尝试了几种带有包装的变体,但都失败了。并且确定我需要 1 个 Collection 项目来列出元素和 1 个元素
-
如果您希望它返回
with数据,您希望您的响应看起来如何?如果您有with数据,Laravel 会将您的响应包装在data数组中,否则它将与您的with数据混淆。例如,它会尝试返回一个类似[$task1, $task2, 'meta' => ['version' => 1]]]的数组。