Laravel 9 ties to make your applications more interactive and ships new features for form validation. It is called precognition. You might have seen on some websites that forms are being validated during their completion. For instance, you have finished filling out a field and immediately receive an error message next to it.
In some cases, this is only frontend validation but now Laravel allows doing it using the backend with minimal effort. In this article we will dive into how to use precognition in Laravel 9.
Table of Contents
Laravel Precognition Tutorial
1. Prepare Environment
I assume that you have already installed and configured an empty Laravel project or any project that you can use for practicing. If not, you can find information on how to install it in this article.
As examples in this article, I will create the ArticleRequest class that can be used to create and update articles. You can do it using this command:
php artisan make:request ArticleRequest
Then, add the following code into app/Http/Requests/ArticleRequest:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ArticleRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules(): array
{
return [
"title" => ["required", "string", "max:1024"],
"content" => ["required", "string", "max:9999"],
"author" => ["required", "string", "max:255"],
];
}
}
After this, create ArticleCreateController using this command:
php artisan make:controller ArticleCreateController
And paste this code into it:
namespace App\Http\Controllers;
use App\Http\Requests\ArticleRequest;
use App\Services\ArticleService;
class CreateArticleController extends Controller
{
public function __invoke(ArticleRequest $request, ArticleService $service)
{
return response()->json("Article created!");
}
}
There is no code for article creation because it is not needed. Precognition works only during the validation step and does not execute the controller code. Don’t forget to register this controller in routes/api.php:
Route::post(
"/articles",
\App\Http\Controllers\CreateArticleController::class
)->name("articles.create");
2. Enable Precognition for Route
If you want to enable precognition feature for any route, just add the precognition middleware to it:
Route::post("/articles", \App\Http\Controllers\CreateArticleController::class)
->middleware(
\Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class
)
->name("articles.create");
Note, that this feature is available only in Laravel 9.35 or higher. If you are using an older version, you have to update it to use precognition.
3. Perform a Precognition Request
If you want to make a precognition request from the frontend, just add the header Precognition with value true to it. I will use Postman to make requests:

You will get validation errors. But if there are no errors, you will get an empty result with a 204 status code:

4. Validate a Specific Field
If you want to validate only a specific field, add the Precognition-Validate-Only header with the field name as the value. For example:

Note, that field filtering works only for rules that are determined by the rules() method. If you use the withValidator() method with any custom validation, it will be executed regardless of the Precognition-Validate-Only header. For example, you can add this code into your ArticleRequest:
public function withValidator(Validator $validator)
{
$validator->after(function (Validator $validator) {
$validator->errors()->add("title", "Some custom error");
$validator->errors()->add("content", "Some custom error");
});
}
After this rerun the query:

You can see that the with validator was executed.
5. Determine Precognitive Requests
The FormRequest class has an isPrecognitive() method that can help understand that this request is precognitive. You can use it to avoid running some heavy validation code in withValidator(). For example:
public function withValidator(Validator $validator)
{
$validator->after(function (Validator $validator) {
$validator->errors()->add("title", "Some custom error");
if ($this->isPrecognitive() === false) {
$validator->errors()->add("content", "Some custom error");
}
});
}
6. Precognition And Rate-Limiting
By default, Laravel has a rate limit for all API requests. It allows performing only 60 requests per minute to each client. Using the precognition feature can increase the number of requests. You can change these settings globally in app/Providers/RouteServiceProvider.php. Just find the configureRateLimiting() method:
protected function configureRateLimiting()
{
RateLimiter::for("api", function (Request $request) {
return Limit::perMinute(60)->by(
$request->user()?->id ?: $request->ip()
);
});
}
Then, change the parameter of the perMinute() method from 60 to the number that you want. It is the number of requests per minute. Read more about rate limiting in this article.
Wrapping Up
In this article I have explained how to use precognition in Laravel to make data validation more efficient and interactive. I think it can make interfaces more user-friendly. Do you like this new feature of Laravel?
How funny, i’ve been frustrated for a long time that there aren’t any client side validators for laravel that use the defined rules, always seemed crazy to have to create a separate set of rules with a JS engine – urgh. done that before and not a happy place.
So I was working on doing exactly this tonight by submitting the form via ajax and adding custom middleware to detect if the request had “validation-only” set and so to return the response immediately after validation instead of continuing to the controller.
Whilst debugging I saw these Precognitive checks and wondering what they were!! Googled it, found your site and now it’s working perfectly. I have lovely forms with green ticks that show up after each field has been completed.
This is a super useful feature that was built into Yii – so in some ways they were ahead of the curve, but it really sucks now compared to Laravel and my life just got better – YAY!!