Чтение данных из vue / cli из Laravel ResourceCollection - PullRequest
0 голосов
/ 14 января 2020

В Laravel 6 back-end rest api app Я использую 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 для коллекций (автономные данные)

и это работает для меня, но мне не нравится, как я получил данные по клиентской части, поэтому для перечисления данных, определенных в элементе управления:

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

и когда мне нужно получить 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], и даже это работает для меня

В моем приложении / 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();
        ...

Если есть способ избавиться от data.data [0] и data.data [0] [0] в части vue / cli?

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

и в результате у меня есть пустые «навыки»: [ноль, ноль, ноль, нуль] результаты. Что не так?

Спасибо!

1 Ответ

1 голос
/ 14 января 2020
  1. Первое, что вы можете сделать, это использовать деструктурирующее назначение , чтобы получить ответные данные из вашего запроса Ax ios:
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].

Второе, что вы можете сделать, в функции toArray вашего TaskCollection класса - вернуть преобразованную коллекцию напрямую, а не заключать ее в массив:
    public function toArray($task)
    {
            return $this->collection->transform(function($task){
                return [
                    'id' => $task->i
                    ...
                ];
            });
    }

Теперь вам не нужно использовать [0] везде. Таким образом, вместо data.data[0][0] вы можете получить доступ к одной задаче с помощью data.data[0].

Чтобы избежать необходимости использовать [0] для единичных ответов, вы должны вернуть JsonResource вместо 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()
            ]
        ];
    }
}
Как я пытался объяснить в комментариях, вы не сможете избежать необходимости заключать свои результаты в ключ (например, 'data') при возврате ненулевых значений из функции with. Если вы мне не верите, временно удалите функцию with, и вы увидите, что сможете получить доступ к своим задачам просто с помощью data (если вы отключили перенос с помощью Resource::withoutWrapping();).

Однако, одну вещь, которую вы можете сделать, это настроить клавишу «wrap». Например, для набора задач может потребоваться, чтобы оно было tasks, а для одной задачи - task. Вы можете просто добавить свойство $wrap к своим TaskCollection и TaskResource классам:

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;
...