Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

samcogan's avatar

Use Form Request with API

I may be missing something obvious here, but I am struggling to find a way to do this. I am using Form Request's to validate my forms and they work great, I am now implementing an API for my app which also needs to validate the data, with the same rules as my forms, so it seems sinsible to re-use the form requests we already created, rather than duplicating these rules. However I can't find much documentation on how to do this, and get the validation errors output as JSON. Am I missing something and this is a bad idea?

What I have done so far is to be able to get the validation object in my API controller and check if validation fails or not, but I can't find a way to display the messages as JSON.

So in my request I have added this:

    protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator)
    {
        $this->validator = $validator;
    }

and then in the controller I can access like this:

    public function store(AirportRequest $request)
    {

        if (isset($request->validator) && $request->validator->fails()) {


        }


    }

But how do I output the the results as JSON? I am using the ellipsesynergie\api-response project for formatting output, so I really just need to get an array of the error messages that can be converted to JSON.

0 likes
6 replies
samcogan's avatar

@paulowdev the issue is I don't have a way to get the validation errors into an array to use in that way.

martinbean's avatar

@samcogan If the validation in the form request class fails, then it’ll throw a ValidationException. You shouldn’t be trying to interrogate the request’s validator and whether it fails or not, as you’re going to be repeating that logic in every controller action.

That said, Laravel’s Exception handler will automatically render validation failures to a JSON array if you pass the correct header with your HTTP request. You need to specify Accept: application/json: https://github.com/laravel/framework/blob/5.3/src/Illuminate/Foundation/Exceptions/Handler.php#L213

4 likes
samcogan's avatar

@martinbean good point, and if I do just let the laravel handler take care of it you are right, it does return JSON. The issue I now have is that it's just return a JSON array:

{

  "name": [
    "The name field is required."
  ],
  "country_id": [
    "The country id field is required."
  ],
  "continent_id": [
    "The continent id field is required."
  ]
}

What I want to be able to do is transform this using fractal to show a formatted set of JSON like:


{
  "error": {
    
"code": "GEN-INTERNAL-ERROR",
    
"http_code": 500,
    
"message": "Validation Failed"

"data":[
    "name": [
      "The name field is required."
    ],
    "country_id": [
      "The country id field is required."
    ],
    "continent_id": [
      "The continent id field is required."
    ]

  ]
 
 }

}


Paschal's avatar

@samcogan Since you are passing it as JSON, you might need to create a variable that holds an array, and in that variable, you push data into the array. Remember, the format you want is like an Object representation in Javascript (That's what JSON stands for anyways) and PHP and JS handles object in a different manner, so you might not be able to get that format with PHP, rather you use pure arrays. On the view and encode that array to JSON with json_encode function, you can access the array data by traversing, it will work

$jsonArr['error'] = [];

$jsonArr['error']['code'] = 'GEN-INTERNAL-ERROR';

$jsonArr['error']['http_code'] = 500;

$jsonArr['error']['message'] = 'Validation Failed';

$jsonArr['error']['data'] = [

       'name' => 'The name field is required.', 

       'country_id' => 'The country id field is required.', 

       'continent_id' => 'The continent id field is required.'

];

<!--- Output: json_encode($jsonArr) --->
{
    "error":{

        "code":"GEN-INTERNAL-ERROR",

        "http_code":500,

        "message":"Validation Failed",

        "data":{ 

            "name": "The name field is required.",

            "country_id": "The country id field is required.",

            "continent_id": "The continent id field is required."
        }
    }
}
MartinsOnuoha's avatar

Not sure if this makes sense for anyone but to have a customized error response, you can modify your request class. Since all your Request classes extends the laravel FormRequest class it means you have access to the failedValidation method within your class, you can overload this method by defining it in your Request class and deciding how to return your error.

class MyForm extends FormRequest {
     ...
    public function failedValidation(Validator $validator)
    {
        $response = ResponseHelper::error($validator->errors(), 'Authentication failed');

        throw (new ValidationException($validator, $response))
            ->errorBag($this->errorBag)
            ->redirectTo($this->getRedirectUrl());
    }
}

Here I have a helper class called ResponseHelper . It looks something like this

use Illuminate\Http\Response as HttpResponse;
use Illuminate\Http\JsonResponse;

class Response extends HttpResponse {
         public static function error(MessageBag|array $errors = [], string $message, int $statusCode = 400): JsonResponse
    {
        return response()->json([
          "error" => [
              "code"  => "GEN-INTERNAL-ERROR",
             "http_code" => 500
          ],
         "data" => $errors
        ], $statusCode);
    }
}
1 like

Please or to participate in this conversation.