从 Laravel ResourceCollection 中读取 vue/cli 中的数据

Reading data from in vue/cli from Laravel ResourceCollection

在 Laravel 6 后端休息 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()
            ]
        ];
    }

}

我在

它对我有用,但我不喜欢在客户端获取数据的方式,因此对于控件中定义的数据列表:

return (new TaskCollection($tasks));

我必须在 vue/cli 应用程序中编写 :

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

当我需要获取 1 个项目时,我在 laravel 的控件中定义:

return (new TaskCollection([$task])); // I have to wrap it as array

我必须在 vue/cli 应用程序中编写:

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);
            });
    }

结果我有空的 "skills":[null,null,null,null] 结果。怎么了?

谢谢!

  1. 您可以做的第一件事是使用 Axios 请求中的 destructuring assignment to get the response data
axios.get(this.apiUrl + '/adminarea/tasks/' + this.task_id, this.credentialsConfig)
    .then(({ data }) => {
        this.taskRow = data.data[0][0]

所以现在 response.data.data[0][0] 缩短为 data.data[0][0]

  1. 您可以做的第二件事是,在 TaskCollection class 的 toArray 函数中,直接 return 转换后的集合,而不是将其包装在数组:
    public function toArray($task)
    {
            return $this->collection->transform(function($task){
                return [
                    'id' => $task->i
                    ...
                ];
            });
    }

现在您不需要在任何地方都使用 [0]。因此,您可以使用 data.data[0].

访问单个任务,而不是 data.data[0][0]
  1. 为避免必须使用 [0] 作为单一响应,您应该 return 一个 JsonResource 而不是 ResourceCollection。为此,您需要将代码从 $this->collection->transform 内部移至新的 JsonResource class。例如:

app/Http/Resources/TaskResource.php:

<?php

namespace App\Http\Resources;

use App\Facades\MyFuncsClass;
use Illuminate\Http\Resources\Json\JsonResource;

class TaskResource extends JsonResource
{
    public function toArray($task)
    {
         return [
                    'id' => $this->id,
                    'name' => $this->name,
                    'slug' => $this->slug,
                    ...
                ];
    }

    public function with($task)
    {
        return [
            'meta' => [
                'version'=>MyFuncsClass::getAppVersion()
            ]
        ];
    }

}

然后您可以 return 单个资源

return new TaskResource($task);

在 Javascript 中,您现在可以 data.data 完成一项任务:

axios.get(this.apiUrl + '/adminarea/tasks/' + this.task_id, this.credentialsConfig)
    .then(({ data }) => {
        this.taskRow = data.data;

您可以重构您的 TaskCollection class 以针对每个任务隐式使用您的新 TaskResource class:

<?php

namespace App\Http\Resources;
use App\Facades\MyFuncsClass;

use Illuminate\Http\Resources\Json\ResourceCollection;

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

    public function with($task)
    {
        return [
            'meta' => [
                'version'=>MyFuncsClass::getAppVersion()
            ]
        ];
    }
}
  1. 就像我试图在评论中解释的那样,当 returning 为非空时,您将无法避免将结果包装在一个键中(如 'data')来自 with 函数的值。如果你不相信我,暂时删除你的 with 功能,你会发现你可以简单地使用 data 访问你的任务(如果你禁用了 Resource::withoutWrapping();).

但是,您可以做的一件事是自定义 "wrap" 键。例如,对于一组任务,您可能希望它是 tasks,而对于单个任务,您可能希望它是 task。您只需将 $wrap 属性 添加到您的 TaskCollectionTaskResource classes:

class TaskCollection extends ResourceCollection
{
    public static $wrap = 'tasks';
    ...
class TaskResource extends JsonResource
{
    public static $wrap = 'task';

现在您将能够使用 data.tasks 访问来自 Javascript 的任务列表和使用 data.task:

的单个任务
axios.post(this.apiUrl + '/adminarea/tasks-filter', filters, this.credentialsConfig)
    .then(({ data }) => {
        this.tasks = data.tasks;
axios.get(this.apiUrl + '/adminarea/tasks/' + this.task_id, this.credentialsConfig)
    .then(({ data }) => {
        this.taskRow = data.task;