Response
Evo provide custom response class Emsifa\Evo\Http\Response\JsonResponse
and Emsifa\Evo\Http\Response\ViewResponse
that is inherit from Emsifa\Evo\Dto
class.
They are all implements Illuminate\Contracts\Support\Responsable
, so that they can be transformed to HTTP response.
You can extend them to your response classes then use your response classes as return type of your controller action to get these benefits:
- Easier to identify how the response data should be.
- It prevents you to send wrong data types. Eg: integer as string, null to non-nullable property, etc.
- It makes Evo knows how to generate your endpoint into OpenAPI.
- It makes Evo knows how to mock the response.
#
Generate Response ClassEvo provide evo:make-response
command to generate response class. Here is its command signature:
php artisan evo:make-response {classname} {...properties} {--view} {--json-template=}
classname
(required): class name to be generated.properties
(optional): class properties.--view
(optional): by defaultevo:make-response
command will useJsonResponse
as parent class, if you want to useViewResponse
, you can add this option.--json-template=
: add this if you want to applyUseJsonTemplate
attribute in generated response class.
For example, we will generate StoreTodoResponse
with command below:
php artisan evo:make-response StoreTodoResponse id:int title:string completed:bool
It will generate app/Http/Responses/StoreTodoResponse
class with following code below:
<?php
namespace App\Http\Responses;
use Emsifa\Evo\Http\Response\JsonResponse;
class StoreTodoResponse extends JsonResponse{ public int $id; public string $title; public bool $completed;}
#
Using Response ClassTo use StoreTodoResponse
you need to put it as return type, then in your controller logic you can use fromArray
method like an example below:
#[Post]public function store(#[Body] StoreTodoDto $dto): StoreTodoResponse{ $todo = Todo::create($dto);
return StoreTodoResponse::fromArray($todo);}
StoreTodoResponse::fromArray
method will create StoreTodoResponse
instance by mapping StoreTodoResponse
public properties with $todo
array values. It also apply type casting for each properties.
#
Using View ResponseIn this example we will create view response in Evo's way.
First let's generate our response view with following command:
php artisan evo:make-response EditTodoResponse todo:TodoDto --view
Since you put TodoDto
type there, it will generate 2 files below:
app/Http/Responses/EditTodoResponse
:<?php namespace App\Http\Responses; use Emsifa\Evo\Http\Response\UseView;use Emsifa\Evo\Http\Response\ViewResponse; #[UseView('edit-todo')]class EditTodoResponse extends ViewResponse{ public TodoDto $todo;}
app/Http/Responses/TodoDto
:<?php namespace App\Http\Responses; use Emsifa\Evo\Http\Response\ResponseDto; class TodoDto extends ResponseDto{}
UseView
attribute above is used to identify what view file should be rendered, and the data passed to the view is its properties, in this case $todo
that is TodoDto
instance.
Now, let's edit TodoDTO
with following properties:
<?php
namespace App\Http\Responses;
use DateTime;use Emsifa\Evo\Http\Response\ResponseDTO;
class TodoDTO extends ResponseDTO{ public int $id; public string $title; public bool $is_completed; public DateTime $created_at; public ?DateTime $updated_at;}
And here is the example on how to use EditTodoResponse
view:
#[Get('{id}')]public function edit(#[Param] int $id): EditTodoResponse{ $todo = Todo::findOrFail($id);
return EditTodoResponse::fromArray(['todo' => $todo]);}
Yes, Evo will automatically transform your Todo
model into TodoDto
instance.
#
Define Response StatusTo define response status in your response class, you can attach Emsifa\Evo\Http\Response\ResponseStatus
attribute in your response class like following code below:
<?php
namespace App\Http\Responses;
use Emsifa\Evo\Http\Response\JsonResponse;use Emsifa\Evo\Http\Response\ResponseStatus;
#[ResponseStatus(201)]class StoreTodoResponse extends JsonResponse{ public int $id; public string $title; public bool $completed;}
Now, when you return StoreTodoResponse
, Evo will set response status to 201
.
#
Using Json TemplateEvo provide Emsifa\Evo\Contracts\JsonTemplate
class to wrap your JsonResponse
instance.
When building RESTful API you may have a convention/standard on how your data formatted.
For example we want our StoreTodoResponse
instead of just rendered like this:
{ "id": 1, "title": "Write documentation", "completed": false}
We want it to be wrapped like this:
{ "status": "ok", "data": { "id": 1, "title": "Write documentation", "completed": false }}
To do this, we have to create a class that implements Emsifa\Evo\Contracts\JsonTemplate
.
This class will be used as a wrapper to all of your JSON response classes.
Let's create file app/Http/Responses/SuccessJsonTemplate.php
with following code:
<?php
namespace App\Http\Responses;
use Emsifa\Evo\Contracts\JsonData;use Emsifa\Evo\Contracts\JsonTemplate;use Emsifa\Evo\Http\Response\JsonResponse;
class SuccessJsonTemplate implements JsonTemplate{ public string $status; public JsonData $data;
/** * @param BaseResponse $response */ public function forJsonResponse(JsonResponse $response): static { $this->status = "ok"; $this->data = $response->getData();
return $this; }}
Now you can use this template using Emsifa\Evo\Http\Response\UseJsonTemplate
like following code below:
<?php
namespace App\Http\Responses;
use Emsifa\Evo\Http\Response\JsonResponse;use Emsifa\Evo\Http\Response\UseJsonTemplate;
#[UseJsonTemplate(SuccessJsonTemplate::class)]class StoreTodoResponse extends JsonResponse{ public int $id; public string $title; public bool $completed;}
Now whenever you return StoreTodoResponse
in your controller, it will be wrapped with SuccessJsonTemplate
data.