Response () не соблюдает структуру ресурса API - PullRequest
0 голосов
/ 05 октября 2018

У меня странная (по крайней мере для моих усталых глаз) проблема, когда при использовании функции response() для возврата ресурса API игнорируется метод with() указанного ресурса, а также не добавляется перенос ключа 'data'.Как ни странно, последняя проблема касается только отдельных ресурсов, а не коллекций.

Я использую Laravel 5.7.

Метод, использующий функцию response(), находится в моем контроллере API, который расширендругими моими контроллерами.

Интересно, что использование $data->response() работает, но я бы тогда ответил, что метод ответа мог бы принимать только коллекции / модели / ресурсы, а не массив, например - на который я полагаюсьдругие методы, которые вызывают respond(), как мой respondWithError() метод.

ApiController

class ApiController extends Controller
{
    public function respond($data, int $status_code = 200)
    {
        try {
            // this is where the issue is
            // simply returning $data prevents the issue
            return response($data)->setStatusCode($status_code);
        } catch (Throwable $t) {
            $this->logger->log('critical', $t->getMessage(), ['exception' => $t]);
            return $this->respondWithError(500);
        }
    }
...
}

ClubController

use App\Http\Resources\Club as ClubResource;
use App\Http\Resources\ClubCollection;
...

class ClubController extends ApiController
{

    /**
     * Display a listing of the resource.
     *
     * @return ClubCollection
     */
    public function index()
    {
       // returns with data key wrapping, but ignores the with() method on the resource
      // collection
       return $this->respond(new ClubCollection(Club::all()));
    }

    public function show($id)
    {

         // returns with no wrapping, and also doesn't implement resource with() method
            return $this->respond(new ClubResource(Club::findOrFail($id)));
    }
...
}

ClubCollection Resource

class ClubCollection extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'data'  => $this->collection,
            'links' => [
                'self'  => 'link-value'
            ],
            'status'    => 'success'
        ];
    }

    // doesn't get called
    public function with($request)
    {
        return [
            'test' => 'this will be ignored '
        ];
    }
}

ClubResource

class Club extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id'                => $this->id,
            'name'              => $this->name,
            'primary_color'     => $this->primary_colour,
            'secondary_colour'  => $this->secondary_colour,
            'tertiary_colour'   => $this->tertiary_colour,
            'logo_url'          => $this->logo_url,
            'narrative'         => $this->narrative
        ];
    }

    // doesn't get called
    public function with($request)
    {
        return [
            'status'    => 'success'
        ];
    }

}

Для пояснения, ни индекс, ни показ конечных точек не приводят к with() метод вызывается.Что еще более важно, метод show() также возвращает плоские данные, без ключа «data», обертывающего их.

api / v1 / clubs / 1 возвращает:

{
"id": 1,
"name": "Johns Ltd",
"primary_color": "18,140,142",
"secondary_colour": "13,148,5",
"tertiary_colour": "187,18,162",
"logo_url": "https://lorempixel.com/640/480/?58550",
"narrative": "Consequatur veniam consectetur sint blanditiis. Minima fugiat voluptatem aperiam corporis assumenda et consequuntur. Voluptate fugiat nulla eos ut. Itaque vero doloribus ea nihil consequuntur vel. Minus error quos occaecati dignissimos."
}

Ожидаемый доход:

{
"data": {
    "id": 1,
    "name": "Johns Ltd",
    "primary_color": "18,140,142",
    "secondary_colour": "13,148,5",
    "tertiary_colour": "187,18,162",
    "logo_url": "https://lorempixel.com/640/480/?58550",
    "narrative": "Consequatur veniam consectetur sint blanditiis. Minima fugiat voluptatem aperiam corporis assumenda et consequuntur. Voluptate fugiat nulla eos ut. Itaque vero doloribus ea nihil consequuntur vel. Minus error quos occaecati dignissimos."
},
"status": "success"
}

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

Ресурсы имеют свой собственный способ возврата ответов с помощью метода response().

Примечание: с помощью метода response() я ссылаюсь на ->response() внутри класса Resource, а не на вспомогательную глобальную функцию response()

например: (new ClubCollection(Club::all()))->response()->setStatusCode(200);

Вы можете добавить оператор выхода в верхней части вашего метода ответа

public function respond($data, int $status_code = 200)
{

    if ($data instanceof JsonResource) {
        return $data->response()->setStatusCode($status_code);
    }
    try {
        // this is where the issue is
        // simply returning $data prevents the issue
        return response($data)->setStatusCode($status_code);
    } catch (Throwable $t) {
        $this->logger->log('critical', $t->getMessage(), ['exception' => $t]);
        return $this->respondWithError(500);
    }
}
0 голосов
/ 05 октября 2018

Чтобы отправить ответ, как вы хотите

return response()->json(["data" => $data, 'status'=>$status], $code);

$code - это код ответа, который может быть 404 500 200 согласно вашему требованию

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...