The shortest path is $request->validate() — it throws a ValidationException that Laravel catches and turns into a redirect-back with errors.
public function store(Request $request)
{
$data = $request->validate([
'title' => ['required', 'string', 'max:160'],
'body' => ['required'],
'tags' => ['nullable', 'array', 'max:5'],
'tags.*'=> ['string', 'max:30'],
]);
Post::create($data);
return redirect()->route('posts.index')->with('success', 'Saved.');
}
$data contains only the keys you validated — safe to pass straight to create().
Rule arrays vs pipe strings
These are equivalent:
'email' => 'required|email|unique:users''email' => ['required', 'email', Rule::unique('users')]
Use the array form when a rule needs arguments (Rule::in([…]), Rule::unique('users')->ignore($id)).
Validation errors in Blade
@error('title') <p class="err">{{ $message }}</p> @enderror
Or check the bag: $errors->first('title').