5

FormRequests in Laravel 5 is good approach for validation and authorizing. But how to procceed if I must validate request that contain data for one to many relationship. For example if I have simple invoice app. One invoice has many services. My form post request contain this data:

 array (size=5)
  'date' => string '2014-11-14' (length=10)
  'num' => string '175' (length=3)
  'client_id' => string '5' (length=1)
  'vat' => string '1' (length=1)
  'services' => 
    array (size=2)
      0 => 
        array (size=3)
          'description' => string 'Service 1' (length=36)
          'value' => string '10' (length=2)
          'items' => string '2' (length=1)
      1 => 
        array (size=3)
          'description' => string 'Service 2' (length=11)
          'value' => string '20' (length=2)
          'items' => string '2' (length=1)

Now in InvoiceFormRequest class I can validate invoice data, but how to proceed with services:

<?php namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Response;

class InvoiceFormRequest extends FormRequest
{
    public function rules()
    {
        return [
            'date' => 'required',
            'num' => 'required',
            'client_id' => 'required',
            'vat' => 'required'
        ];
    }

    public function authorize()
    {
        return true;
    }
}

Thanks in advance!


Update: As I've read here in Laravel 5.2 will can write something like this:

'services.*.description' => 'required',
'services.*.value' => 'required:numeric',
'services.*.items' => 'required:integer'
fireball70
  • 368
  • 1
  • 4
  • 14

3 Answers3

2

Now in Laravel 5.2 we have Array validation:

'services.*.description' => 'required',
'services.*.value' => 'required:numeric',
'services.*.items' => 'required:integer'

http://laravel.com/docs/5.2/releases#laravel-5.2

fireball70
  • 368
  • 1
  • 4
  • 14
1

You could be using the "array" option for the "services" parameters in the rules, but of course this wouldn't validate any data contained in each element.

http://laravel.com/docs/master/validation#rule-array

So, I'd probably suggest to use something like Marwelln said, with a custom validator, as well as the "array" rule.

Your rules would probably end up looking like this

public function rules()
{
    return [
        'date' => 'required',
        'num' => 'required',
        'client_id' => 'required',
        'vat' => 'required',
        'services' => 'array|services'
    ];
}

and the custom validator could be something like this (you should put this in a ServiceProvider)

Validator::extend('services', function($attribute, $value, $parameters)
{

    //foreach $value as $service
          //validate $service['description'], $service['value'], $service['items']

    //return true or false depending on the validation of each element
});

hope it helped you to find the right direction!

LittleBobbyTables - Au Revoir
  • 32,008
  • 25
  • 109
  • 114
0

Perhaps a more automatic way to implement the method:

Validator::extend('ingredients', function($attribute, $value, $parameters)
{
    $model = app("App\Models\\".Str::singular(Str::studly($attribute)));
    return Validator::make($value, $model::$rules)->validate();
});
Dharman
  • 30,962
  • 25
  • 85
  • 135
AlanSmith
  • 71
  • 6