You are currently viewing Como validar dados de request API Laravel
validar dados

Como validar dados de request API Laravel

Introdução

Ao trabalhar com APIs, é muito importante validar dados recebidos nas requisições, para garantir que estará trabalhando com os dados corretos.

Sendo assim, essa é a primeira coisa a se fazer ao receber uma requisição.

Validar dados corretamente pode impedir que uma série de bugs apareça, seja validar um campo requerido, o tipo da informação, limite de dados e entre outros.

Nesse post você vai ver como validar dados recebidos em uma request por uma API Laravel, seja validando dentro do Controller ou com uma camada de validar dados.

Para enviar as requisições, vou utilizar o Postman, que é uma plataforma utilizada para trabalhar com requisições. Outro software que também faz o mesmo tipo de serviço é o Insomnia, que já usei anteriormente e também é muito bom.

Criei uma API simples que só tem o método POST, estou simulando uma API de blog onde irá validar dados de um artigo a ser cadastrados.

Os artigos vão ter quatro informações, são elas título, descrição, quantidade de artigos relacionados e data de agendamento.

Todos os dados vão ser requeridos e cada um tem seu tipo.

Vou deixar aqui abaixo a migration que utilizei, a rota e o controller:

// migration
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->id();

            $table->string('title', 100);
            $table->text('description');
            $table->integer('quantity_articles_related');
            $table->timestamp('schedule_date');

            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('articles');
    }
};

//rota (/routes/api.php)
<?php
use App\Http\Controllers\ArticleController;
use Illuminate\Support\Facades\Route;

Route::post('articles', [ArticleController::class, 'store']);
//controller (/app/Http/Controllers)
<?php

namespace App\Http\Controllers;

use App\Models\Article;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class ArticleController extends Controller
{
  public function store(Request $request)
    {
        //validação dos dados aqui
        $article = new Article($request->all());

        if( $article->save() ){
            return response()->json([
                "message" => "Article created",
                "data" => $article
            ], 201);
        }
    }
}

Validar dados no controller

A validação mais simples a se fazer, é dentro do controller, onde você recebe os dados da requisição, e pode validar antes de fazer qualquer coisa.

No código que mostrei acima, antes de pegar todos os dados com o $request->all() e criar a model de Artigos, vamos adicionar a validação.

Vou utilizar o Validator::make do Laravel para criar as validações para cada campo.

Vou informar que cada campo é requerido, também o tipo de cada campo e o range de dados, no caso do título precisa ter entre 3 e 100 caracteres.

Caso você queira ver todos os tipos de validação de dados do Laravel, veja aqui.

$validator = Validator::make($request->all(),[
    'title' => 'required|string|min:3|max:100',
    'description' => 'required',
    'quantity_articles_related' => 'required|numeric',
    'schedule_date' => 'required|date',
]);

Com essa validação, para saber se os dados não estão válidos é possível fazer utilizando $validator->fails(), caso seja true, então há algum dado incorreto, então vou colocar isso numa condicional, para conseguir retornar os erros.

É possível obter os erros com $validator->errors(), essa função vai retornar um array com cada erro encontrado na validação, assim é possível retornar esses erros na API para dizer que não foi possível incluir:

if($validator->fails()){
    return response()->json([
        "error" => 'validation_error',
        "message" => $validator->errors(),
    ], 422);
}

É importante também mandar o statuscode como 422, que informa que os dados não foram validados.

Com essas validações, caso seja enviado uma request que tenham os dados válidos, esse será o retorno:

validar dados 1

E caso seja preenchido com informações que estejam faltando algo, esse será o retorno:

A função completa do Controller fica assim:

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(),[
            'title' => 'required|string|min:3|max:100',
            'description' => 'required',
            'quantity_articles_related' => 'required|numeric',
            'schedule_date' => 'required|date',
        ]);

        if($validator->fails()){
            return response()->json([
                "error" => 'validation_error',
                "message" => $validator->errors(),
            ], 422);
        }

        $article = new Article($request->all());

        if( $article->save() ){
            return response()->json([
                "message" => "Article created",
                "data" => $article
            ], 201);
        }
    }

Criar camada de validação (form request)

A validação no controller irá funcionar bem, porém eu vejo alguns problemas nessa abordagem.

Dessa forma, é adicionado uma responsabilidade a mais no controller, que é a de validar dados, o código pode ficar maior a medida que os campos aumentem e caso precise de validações mais complexas talvez não será possível fazer.

Para resolver isso, é possível criar um form request no Laravel, que vai ficar entre a request e o controller, e servirá para validar dados.

Além de validar dados, será possível personalizar a mensagem retornada, escrever lógicas mais complexas de validação e entre outros.

E para criar esse arquivo de validação, é possível fazer com o seguinte comando no terminal:

php artisan make:request ArticleStoreRequest

O Laravel irá criar um arquivo no diretório App\Http\Requests e dentro desse arquivo iremos escrever as validações.

Ao ser criado, o arquivo já vem com o método rules(), vamos pegar a lógica de validação colocada no controller, e vamos mover para esse método, deixando o rules() dessa forma:

public function rules()
{
    return [
        'title' => 'required|string|min:3|max:100',
        'description' => 'required',
        'quantity_articles_related' => 'required|numeric',
        'schedule_date' => 'required|date',
    ];
}

Outro método adicionado junto com a criação do artigo é o authorize(), por padrão ele vem como falso, esse método é relacionado a validação de autorização de acesso a essa rota, como não estamos tratando disso nesse post, troque para true, para funcionar normalmente:

public function authorize()
{
    return true;
}

Agora no controller, vamos precisar trocar a chamada do método store, para indicar que utilizaremos o novo validador, e com isso também podemos remover todo o código de validação do controller, vai ficar assim:

public function store(ArticleStoreRequest $request)
{
    $article = new Article($request->validated());

    if( $article->save() ){
        return response()->json([
            "message" => "Article created",
            "data" => $article
        ], 201);
    }
}

Pronto, agora já temos um resultado igual ao anterior, caso a gente refaça as requisições para criar o registro com os dados válidos e teremos o erro com os dados inválidos.

Porém agora já temos um pouco menos de código e também as responsabilidades separadas.

Personalizando mensagens de erro

Agora podemos personalizar as mensagens de erro a serem exibidas.

E para fazer isso não é difícil, ao arquivo ArticleStoreRequest.php, vamos adicionar um método chamado messages().

Esse método vai retornar um array, contendo a chave que será validada e a mensagem correspondente:

public function messages()
{
    return [
        'title.required' => 'O título é obrigatório',
        'title.string' => 'O título precisa ser uma string',
        'title.min' => 'O título precisa ter no mínimo 3 caracteres',
        'title.max' => 'O título precisa ter no máximo 100 caracteres',

        'description.required' => 'A descrição é obrigatória',

        'quantity_articles_related.required' => 'A quantidade de artigos relacionados é obrigatória',
        'quantity_articles_related.numeric' => 'A quantidade de artigos relacionados precisa ser um número',

        'schedule_date.required' => 'A data de agendamento é obrigatória',
        'schedule_date.date' => 'A data de agendamento precisa ser uma data',
    ];
}

Repare que escrevemos uma mensagem personalizada para cada tipo de validação, seja required, max, min, string, date e entre outras, você pode personalizar todas as mensagens.

Exemplo 1:

Exemplo 2:

Conclusão

Validar dados é essencial para todas as aplicações, dessa forma é possível garantir que estaremos trabalhando com dados seguros.

O Laravel tem algumas formas de validar dados e ajuda muito no dia a dia, pois é fácil e prático.

Caso precise validar dados de alguma forma mais personalizada ou específica, recomendo que de uma olhada na documentação, que provavelmente irá atender ao seu caso.

Para ver outros canais onde o posto conteúdo veja os Links do Programando Soluções.

Até o próximo post 🙂

Referências

https://laravel.com/docs/9.x/validation

https://medium.com/@sgandhi132/how-to-validate-an-api-request-in-laravel-35b46470ba88

https://www.postman.com/downloads/

https://insomnia.rest/download

https://laravel.com/docs/9.x/validation#available-validation-rules

Este conteúdo te ajudou de alguma forma?