Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How i can return a customized response in a FormRequest class in Laravel 5.5?

I am making an API and i want return the array of errors with a format as the one that $validator->errors(); generates when i validate the request by the manual way. But i cant manipulate the response. I wanna find thhe correct way to make it.

This could be done in Laravel 5.4 with the formatErrors method and including the Illuminate\Contracts\Validation\Validator class in the FormRequest class but for version 5.5 it does not work. I do not know how to do it.

This is my Controller:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests\ProductRequest;
use Illuminate\Validation\Rule;
use App\Product;

class ProductController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(ProductRequest $request)
    {
        $products = Product::where('code', 'LIKE', '%'.$request->input('search').'%')
        ->where('name', 'LIKE', '%'.$request->input('search').'%')
        ->paginate(10);
        $products->withPath($request->fullUrl());
        return $products;
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {

    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(ProductRequest $request)
    {
        $product = new Product($request->validated());
        $product->save();
        return response('', 201);
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $product = Product::find($id);
        return response($product, 200);
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(ProductRequest $request, $id)
    {
        $product = Product::find($id);
        $product->fill($request->validated());
        $product->save();
        return response('', 200);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $product = Product::find($id);
        $product->delete();
        return response('', 204);
    }
}

This is mi FormRequest class

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class ProductRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        switch($this->method())
        {
            case 'GET':
            {
                return [
                    'code' => 'string',
                    'name' => 'string',
                ];
            } break;
            case 'POST':
            {
                return [
                    'code' => 'required|unique:Products,code',
                    'name' => 'required',
                    'description' => 'required',
                    'quantity' => 'required|min:0',
                    'price' => 'required|numeric',
                    'extemp' => [
                        Rule::in(['tax', 'free']),
                    ]
                ];
            } break;
            case 'PUT':
            {
                return [
                    'code' => 'unique:products,code,'.$this->route('product'),
                    'name' => 'string:min:1',
                    'description' => 'string|min:1',
                    'quantity' => 'integer|min:0',
                    'price' => 'numeric',
                    'extemp' => [
                        Rule::in(['tax', 'free']),
                    ],
                ];
            } break;
            case 'PATCH': break;
            case 'DELETE': break;
            default:
            {
                return [];
            } break;
        }
    }

    /**
     * Get the error messages for the defined validation rules.
     *
     * @return array
     */
    public function messages()
    {
        return [
            //Product
            'code.required' => 'El :attribute es obligatorio.',
            'code.unique' => 'El :attribute ya se encuentra registrado.',
            'name.required' => 'El :attribute es obligatorio.',
            'name.min' => 'El :attribute es obligatorio.',
            'description.required' => 'El :attribute es obligatorio.',
            'description.min' => 'El :attribute es obligatorio.',
            'quantity.required' => 'La :attribute es obligatoria.',
            'quantity.integer' => 'La :attribute debe ser un número entero.',
            'quantity.min' => 'La :attribute debe ser al menos :min.',
            'price.required' => 'El :attribute es obligatorio.',
            'price.numeric' => 'El :attribute debe ser un valor numérico.',
            'extemp.in' => 'El :attribute seleccionado es inválido.',
        ];
    }
    public function attributes(){
        return [
            'code' => 'código',
            'name' => 'nombre',
            'description' => 'descripción',
            'quantity' => 'cantidad',
            'price' => 'precio',
            'extemp' => 'exento',
        ];
    }
}

The Response what i have:

{
    "message": "The given data was invalid.",
    "errors": {
        "code": [
            "El código es obligatorio."
        ],
        "name": [
            "El nombre es obligatorio."
        ],
        "description": [
            "El descripción es obligatorio."
        ],
        "quantity": [
            "La cantidad es obligatoria."
        ],
        "price": [
            "El precio es obligatorio."
        ]
    }
}

The Response what i want (with $validator->errors();)

[
    "El código es obligatorio.",
    "El nombre es obligatorio.",
    "El descripción es obligatorio.",
    "La cantidad es obligatoria.",
    "El precio es obligatorio."
]
like image 651
Simón Farias Avatar asked Sep 20 '17 14:09

Simón Farias


2 Answers

You have to override the failedValidation() method and issue the exception with the response what you want. So, you need to use Illuminate\Contracts\Validation\Validator and Illuminate\Http\Exceptions\HttpResponseException in the RequestForm class, and override the failedValidation() method:

protected function failedValidation(Validator $validator) { 
        throw new HttpResponseException(response()->json($validator->errors()->all(), 422)); 
}
like image 83
Simón Farias Avatar answered Oct 05 '22 15:10

Simón Farias


For this Need to override failedValidation() function in your Request file.

protected function failedValidation(Validator $validator)
{
    throw new HttpResponseException(response()->json([
      'errors' => $validator->errors(),
      'status' => false
    ], 422));
}

To make it work use these namespaces:

For laravel 5.4 and above:

 use Illuminate\Contracts\Validation\Validator;

 use Illuminate\Http\Exceptions\HttpResponseException;

description here

Below laravel 5.4:

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exception\HttpResponseException;

description here

like image 39
PHP Worm... Avatar answered Oct 05 '22 16:10

PHP Worm...