27

It's the first time i am using validation in laravel. I am trying to apply validation rule on below json object. The json object name is payload and example is given below.

payload = {
  "name": "jason123",
  "email": "email@xyz.com",
  "password": "password",
  "gender": "male",
  "age": 21,
  "mobile_number": "0322 8075833",
  "company_name": "xyz",
  "verification_status": 0,
  "image_url": "image.png",
  "address": "main address",
  "lattitude": 0,
  "longitude": 0,
  "message": "my message",
  "profession_id": 1,
  "designation_id": 1,
  "skills": [
    {
      "id": 1,
      "custom" : "new custom1"
    }
   ]
}

And the validation code is like below, for testing purpose i am validating name as a digits. When i executed the below code, the above json object is approved and inserted into my database. Instead, it should give me an exception because i am passing name with alpha numeric value, am i doing something wrong:

public function store(Request $request)
{

    $this->validate($request, [
        'name' => 'digits',
        'age' => 'digits',
        ]);
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
MTA
  • 1,033
  • 5
  • 16
  • 37
  • you should use `integer` to accept only numbers or `alpha` for only alphabetic characters – Onix May 16 '17 at 12:15

6 Answers6

35

Please try this way

use Validator;

public function store(Request $request)
{
    //$data = $request->all();
    $data = json_decode($request->payload, true);
    $rules = [
        'name' => 'digits:8', //Must be a number and length of value is 8
        'age' => 'digits:8'
    ];

    $validator = Validator::make($data, $rules);
    if ($validator->passes()) {
        //TODO Handle your data
    } else {
        //TODO Handle your error
        dd($validator->errors()->all());
    }
}

digits:value

The field under validation must be numeric and must have an exact length of value.

MTA
  • 1,033
  • 5
  • 16
  • 37
Quynh Nguyen
  • 2,959
  • 2
  • 13
  • 27
  • 5
    if ($validator->fails()) { return response()->json($validator->messages(), 200); } Is a better way to handle the messages – rchatburn May 16 '17 at 12:21
  • @rchatburn Yes. I'm using this way for API. – Quynh Nguyen May 16 '17 at 12:35
  • 5
    @rchatburn, heh... longtime since you commented this, but I think it should return 422 instead of 200... regards. – Erubiel Apr 02 '19 at 20:18
  • A 400 is better than a 422 as 422 is WebDAV specific. See https://stackoverflow.com/questions/16133923/400-vs-422-response-to-post-of-data – Capsule Apr 11 '23 at 02:30
12

I see some helpful answers here, just want to add - my preference is that controller functions only deal with valid requests. So I keep all validation in the request. Laravel injects the request into the controller function after validating all the rules within the request. With one small tweak (or better yet a trait) the standard FormRequest works great for validating json posts.

Client example.js

var data = {first: "Joe", last: "Dohn"};
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST",'//laravel.test/api/endpoint');
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.send(JSON.stringify(data));

project/routes/api.php

Route::any('endpoint', function (\App\Http\Requests\MyJsonRequest $request){
    dd($request->all());
});

app/Http/Requests/MyJsonRequest.php (as generated by php artisan make:request MyJsonRequest)

<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class MyJsonRequest extends FormRequest{

    public function authorize(){
        return true;//you'll want to secure this
    }

    public function rules(){
        return [
            'first' => 'required',
            'last'  => 'required|max:69',
        ];
    }

    //All normal laravel request/validation stuff until here
    //We want the JSON...
    //so we overload one critical function with SOMETHING LIKE this
    public function all($keys = null){
        if(empty($keys)){
            return parent::json()->all();
        }

        return collect(parent::json()->all())->only($keys)->toArray();
    }
}
Tarek Adam
  • 3,387
  • 3
  • 27
  • 52
3

Your payload should be payload: { then you can do

$this->validate($request->payload, [
    'name' => 'required|digits:5',
    'age' => 'required|digits:5',
    ]);

or if you are not sending the payload key you can just use $request->all()

Gaurav Dave
  • 6,838
  • 9
  • 25
  • 39
rchatburn
  • 732
  • 4
  • 13
  • I am sending json object with the key "payload" but i get error when i try to access it like this $request->payload error:validate() must be an instance of Illuminate\Http\Request, string given. – MTA May 16 '17 at 12:28
  • @MTA In that case use Quỳnh Nguyễn answer and replace $request->all() with $request->payload – rchatburn May 16 '17 at 12:48
1
 $request->merge([
            'meta_data' => !is_null($request->meta_data) ? json_encode($request->meta_data) : null
        ]);

validator = Validator::make($request->all(), [
      'meta_data' => 'nullable|json'
        ]);
Vigikaran
  • 725
  • 1
  • 10
  • 27
0

Use the Validator factory class instead using validate method derived from controller's trait. It accepts array for the payload, so you need to decode it first

\Validator::make(json_decode($request->payload, true), [
    'name' => 'digits',
    'age' => 'digits',
]);
Chay22
  • 2,834
  • 2
  • 17
  • 25
0

Following the example of @tarek-adam, in Laravel 9 it would be:

<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class MyJsonRequest extends FormRequest{

    public function authorize(){
        return true;//you'll want to secure this
    }

    public function rules(){
        return [
            'first' => 'required',
            'last'  => 'required|max:69',
        ];
    }

    //All normal laravel request/validation stuff until here
    //We want the JSON...
    //so we overload one critical function with SOMETHING LIKE this
    public function validationData()
    {
        if(empty($this->all())){
            $res = [
                'success' => false,
                'message' => 'Check your request',
            ];  


            throw new HttpResponseException(
                response()->json($res, 422)
            );
        }

        return $this->all();
    }
}