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

RanYefet's avatar

How to return Error code of validation fields in Rest API

Hello,

It's my first post here :) There is something I'm trying to figure out which I can't seem to find a solution. I'm building Restful API and lets say I have a book resource and when client make a POST request to /books, I use the following validation in my controller/model:

$validator = Validator::make(Input::all(), [
    'title' => 'required',
    'author'    => 'required'
]);

And when the validation fails I return the error messages in the JSON response.

return Response::make([
    'message'   => 'Validation Failed',
    'errors'        => $validator->errors()
]);

The response will look something like:

{
    "message": "Validation Failed",
    "errors": {
        "title": [
                "The title field is required."
        ],
        "author": [
                "The author field is required."
        ]
    }
}

Now for my issue, I like to add an error code for each validation error so I could handle errors based on error code.

I like that my response will be something like:

{
    "message": "Validation Failed",
    "errors": {
        "title": {
                "code": "required_field",
                "message": "The title field is required."
        },
        "author": {
                "code": "required_field",
                "message": "The author field is required."
        }
    }
}

What is the recommended way to do this? Should I extend the Validator class or can you think of a better way to accomplish it?

Thanks, Ran.

0 likes
8 replies
usman's avatar
usman
Best Answer
Level 27

Hi, There could be multiple validation errors associated with a single field so you may need to have a top level array for each field that needs to be validated, so the correct structure in this case would be:

{
    "message": "Validation Failed",
    "errors": {
        "title": [
        {
                    "code": "required_field",
                    "message": "The title field is required."
        },
        {
            "code": "max_field_error",
            " message": "The title may not be greater than 50 characters."
        }   
    ],
        "author":[
        {
                "code": "required_field",
                "message": "The author field is required."
            }
    ]
    }
}

Yes you're right you will need to extend the validator class and override the addError method. Here is how you can do it in Laravel 5:

// app/Validators/RestValidator.php
<?php namespace App\Validators;

use Illuminate\Support\MessageBag;
use Illuminate\Validation\Validator;

class RestValidator extends Validator {

    /**
     * Add an error message to the validator's collection of messages.
     *
     * @param  string  $attribute
     * @param  string  $rule
     * @param  array   $parameters
     * @return void
     */
    protected function addError($attribute, $rule, $parameters)
    {
        $message = $this->getMessage($attribute, $rule);

        $message = $this->doReplacements($message, $attribute, $rule, $parameters);

        $customMessage = new MessageBag();

        $customMessage->merge(['code' => strtolower($rule.'_rule_error')]);
        $customMessage->merge(['message' => $message]);

        $this->messages->add($attribute, $customMessage);//dd($this->messages);
    }

}

Add the binding in the boot method of `App\Providers\AppServiceProvider.php:

use App\Validators\RestValidator;
...
...
    public function boot()
    {
        \Validator::resolver(function($translator, $data, $rules, $messages)
        {
            return new RestValidator($translator, $data, $rules, $messages);
        });
    }

And that's it. I have tested it like this:

Route::get('/validation',function(){
    $fields = [
        'title' => '3ss',
    ];
    $rules = [
            'title' => 'required|max:2|alpha'
    ];
    $valid = Validator::make($fields, $rules);
    return [
        'message' => 'validation_faild',
        'errors' => $valid->errors()
    ];
});

Output:

{
    "message":"validation_faild",
    "errors":{
        "title":[
                {
                    "code":"max_rule_error",
                    "message":"The title may not be greater than 2 characters."
                },
                {
                    "code":"alpha_rule_error",
                    "message":"The title may only contain letters."
                }
            ]}
}

Hope it helps!

6 likes
RanYefet's avatar

Wow! I didn't expect for a full solution, just a direction. Good point on the multiple error messages per field ;) Thank you very much! I'll check it out.

RanYefet's avatar

Hi @usman I didn't understand the part with the AppServiceProvider, can you please explain?

Edit: never mind, I found out I needed to implement register method on my service.

novacreator's avatar

@usman (and all others)

How do i have to modify the code to only use this validator on rest/ajax requests?

1 like
jvrhenen's avatar

There are some changes in the Validator for Laravel 5.4+.

protected function addError($attribute, $rule, $parameters)
    {
        $message = $this->getMessage($attribute, $rule);

        $message = $this->doReplacements($message, $attribute, $rule, $parameters);

        $customMessage = new MessageBag();

        $customMessage->merge(['code' => strtolower($rule.'_rule_error')]);
        $customMessage->merge(['message' => $message]);

        $this->messages->add($attribute, $customMessage);//dd($this->messages);
    }

Should be

protected function addFailure($attribute, $rule, $parameters)
    {
        $message = $this->getMessage($attribute, $rule);

        $message = $this->makeReplacements($message, $attribute, $rule, $parameters);

        $customMessage = new MessageBag();

        $customMessage->merge(['code' => strtolower($rule.'_rule_error')]);
        $customMessage->merge(['message' => $message]);

        $this->messages->add($attribute, $customMessage);//dd($this->messages);
    }
pandeptwidyaop's avatar

Laravel 6.0

public function addFailure($attribute, $rule, $parameters = [])
    {
        if (! $this->messages) {
            $this->passes();
        }

        $message = $this->getMessage($attribute, $rule);

        $message = $this->makeReplacements($message, $attribute, $rule, $parameters);

        $customMessage = new MessageBag();

        $customMessage->merge(['code' => strtolower($rule.'_error')]);
        $customMessage->merge(['message' => $message]);

        $this->messages->add($attribute, $customMessage);
        
        $this->failedRules[$attribute][$rule] = $parameters;
    }

Please or to participate in this conversation.