Validation in Laravel is pretty easy. It basically gives you two options where to validate an incoming request:
inside a controller action
via a dedicated Form Request
1<?php namespace App\Http\Controllers; 2 3use App\Http\Controllers\Controller; 4 5class PostController extends Controller 6{ 7 public function store(Request $request) 8 { 9 $validatedData = $request->validate([10 'title' => 'required|unique:posts|max:255',11 'body' => 'required',12 ]);13 14 // The blog post is valid...15 }16}
This is a pretty simple yet powerful approach. You just ask the request to validate itself based on the passed rules. If the validation fails, the method creates a proper error message and send it back to the view. If the validation passes, it just moves on with the rest of the code inside the action.
This can get very expressive if you validate a long form with more than 10 fields; but there is something we can do about.
1<?php namespace App\Http\Requests; 2 3use Illuminate\Foundation\Http\FormRequest; 4 5class PostStoreRequest extends FormRequest 6{ 7 public function authorize() 8 { 9 return true;10 }11 12 public function rules()13 {14 return [15 'title' => 'required|unique:posts|max:255',16 'body' => 'required',17 ];18 }19}
1<?php namespace App\Http\Controllers; 2 3use App\Http\Controllers\Controller; 4use App\Http\Requests\SingingCircleRequest; 5 6class PostController extends Controller 7{ 8 public function store(PostStoreRequest $request) 9 {10 // You can just pull the data out of PostStoreRequest11 }12}
Here we need to create a Form Request object with a meaningful name.
$ php artisan make:request PostStoreRequest
Then, we define the rules in rules()
and pass the Form Request object to the action. We are now able to get the validated data out of PostStoreRequest
.
I am using In-Action validation for rapid development. I like to see the rules close to the code. In this phase I need to adjust them quickly without fiddling too much with several files.
In later state, I usually move them to a FormRequest class. The benefits are:
cleaner and shorter action
if the validation fails, the action will never hit
the Form Request object has a dedicated place to authorize the action
But where light is, is also some darkness:
a Form Request object for any action who handles user input
your validation rules are spread and are hidden in all these files
While the first point is just like it is, the last point can be addressed.
Since we try to validate and store a blog post, we also have a BlogPost model. Fine! Now, just move the rules from where ever they are to the model and store them in a static variable:
1// Validate inside an action. 2<?php namespace App\Models; 3 4use Illuminate\Database\Eloquent\Model; 5 6class BlogPost extends Model 7{ 8 public static $createRules = [ 9 'title' => 'required|unique:posts|max:255',10 'body' => 'required',11 ];12 13 public static $updateRules = [14 'title' => 'required|unique:posts|max:255',15 'body' => 'required',16 ];17}
1// In-Action Validation with rules from Model 2<?php namespace App\Http\Controllers; 3 4use App\Http\Controllers\Controller; 5use App\Models\BlogPost; 6 7class PostController extends Controller 8{ 9 public function store(Request $request)10 {11 $validatedData = $request->validate(BlogPost::$createRules);12 // The blog post is valid...13 }14}
1// Form Request Validation with rules from Model 2<?php namespace App\Http\Requests; 3 4use App\Models\BlogPost; 5use Illuminate\Foundation\Http\FormRequest; 6 7class PostStoreRequest extends FormRequest 8{ 9 public function rules()10 {11 return BlogPost::$createRules12 }13}
You can even go one step further and combine two or more rules together.
1<?php namespace App\Http\Requests; 2 3use App\Models\BlogPost; 4use Illuminate\Foundation\Http\FormRequest; 5 6class PostStoreRequest extends FormRequest 7{ 8 public function rules() 9 {10 return array_merge(BlogPost::$createRules, Author::$createRules);11 }12}