首页 > 解决方案 > 从 Laravel ResourceCollection 从 vue/cli 中读取数据

问题描述

在 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)中找到了这个决定

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

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] 结果。怎么了 ?

谢谢!

标签: laravellaravel-resource

解决方案


  1. 您可以做的第一件事是使用解构赋值从您的 Axios 请求中获取响应数据:
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. 您可以做的第二件事是,在toArray您的类的函数中TaskCollection,直接返回转换后的集合,而不是将其包装在数组中:
    public function toArray($task)
    {
            return $this->collection->transform(function($task){
                return [
                    'id' => $task->i
                    ...
                ];
            });
    }

现在你不需要[0]到处使用了。因此,您可以使用 代替data.data[0][0]访问单个任务data.data[0]

  1. 为了避免必须使用[0]单数响应,您应该返回 aJsonResource而不是 a ResourceCollection。为此,您需要将代码从内部移动$this->collection->transform到新JsonResource类。例如:

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 new TaskResource($task);

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

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

您可以重构您的TaskCollection类以隐式地TaskResource为每个任务使用您的新类:

<?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. 就像我试图在评论中解释的那样,在从函数'data'返回非空值时,您将无法避免将结果包装在一个键(如)中。with如果您不相信我,请暂时删除您的with功能,您会发现您只需使用data(如果您禁用了包装Resource::withoutWrapping();)即可访问您的任务。

但是,您可以做的一件事是自定义“换行”键。例如,对于您可能希望的任务集合,tasks对于单个任务,只需task. 您可以简单地为您的和类添加一个$wrap属性:TaskCollectionTaskResource

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

现在,您将能够使用 Javascript 访问任务列表,data.tasks以及使用以下命令访问单个任务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;

推荐阅读