$request->validate() takes field names and rule lists (arrays, or |-separated strings). It returns only the fields that had rules, or throws a ValidationException that ends the action.
public function store(Request $request, Product $product): RedirectResponse
{
$data = $request->validate([
'author' => ['required', 'string', 'max:80'],
'rating' => ['required', 'integer', 'between:1,5'],
'body' => ['bail', 'required', 'string', 'min:20', 'max:2000'],
]);
$product->reviews()->create($data);
return to_route('products.show', $product)->with('status', 'Review received.');
}The same bad review, posted once as a form and once asking for JSON:
$ R=$B/products/1/reviews; F='author=&rating=9&body=Too short'
$ curl -si -H "$H" -H "Referer: $R/create" -d "$F" $R | grep -E '^(HTTP|Loc|Set-Cookie: lar)' \
| cut -c1-64
HTTP/1.1 302 Found
Location: http://127.0.0.1:8308/products/1/reviews/create
Set-Cookie: laravel-session=eyJpdiI6IjZZY0lTT0FZWEE0ZW4xZEpKVER1
$ curl -si -H "$H" -H 'Accept: application/json' -d "$F" $R | grep -E '^(HTTP|Con.*json|\{)' \
| fold -w 90
HTTP/1.1 422 Unprocessable Content
Content-Type: application/json
{"message":"The author field is required. (and 2 more errors)","errors":{"author":["The au
thor field is required."],"rating":["The rating field must be between 1 and 5."],"body":["
The body field must be at least 20 characters."]}}The browser went back to the Referer with the errors in its session. The JSON client got them directly, since expectsJson() is true for that header and for XHR calls; the skeleton's bootstrap/app.php also renders JSON for every api/* path. bail stops a field at its first failure. The returned array is a mass-assignment filter too: a review posted with is_approved=1 was stored unapproved, where create($request->all()) would have approved it.