Skip to content

FormRequest side effects after introducing Laravel Precognition #48685

Closed
@lucaspanik

Description

@lucaspanik

Laravel Version

v10.27.0

PHP Version

8.2.11

Database Driver & Version

No response

Description

In version 9.32.0 and earlier, the validationData() method was called before the rules() method in the FormRequest, which provided the possibility of changing the data before being sent to rules().

protected function createDefaultValidator(ValidationFactory $factory)
{
return $factory->make(
$this->validationData(), $this->container->call([$this, 'rules']),
$this->messages(), $this->attributes()
)->stopOnFirstFailure($this->stopOnFirstFailure);
}

As can be seen in the print below.
image


With the acceptance of PR [9.x] Introduce Laravel Precognition #44339, a "side effect" was introduced in the sequences in which methods are called.

From version 9.33.0 and later, the rules() method is being called before validationData(), not giving the possibility of making changes to the data before being sent to rules();

protected function createDefaultValidator(ValidationFactory $factory)
{
$rules = $this->container->call([$this, 'rules']);
if ($this->isPrecognitive()) {
$rules = $this->filterPrecognitiveRules($rules);
}
return $factory->make(
$this->validationData(), $rules,
$this->messages(), $this->attributes()
)->stopOnFirstFailure($this->stopOnFirstFailure);
}

As can be seen in the print below.
image


I confirmed that the same code is in version 10 as well:

https://github.com/laravel/framework/blob/10.x/src/Illuminate/Foundation/Http/FormRequest.php#L119C96-L119C96

protected function createDefaultValidator(ValidationFactory $factory)
{
$rules = method_exists($this, 'rules') ? $this->container->call([$this, 'rules']) : [];
$validator = $factory->make(
$this->validationData(), $rules,
$this->messages(), $this->attributes()
)->stopOnFirstFailure($this->stopOnFirstFailure);
if ($this->isPrecognitive()) {
$validator->setRules(
$this->filterPrecognitiveRules($validator->getRulesWithoutPlaceholders())
);
}
return $validator;
}

Steps To Reproduce

Use the code below to notice that there is a change in the sequence in which the methods are executed:

// Route

Route::post('home', [HomeController::class, 'index']);

// Controller
class HomeController extends Controller
{
    public function index(HomeTestRequest $request)
    {
        dd('HomeController');        
    }
}

// Form Request
class HomeTestRequest extends FormRequest
{
    /**
     * Get data to be validated from the request.
     *
     * @return array
     */
    public function validationData()
    {
        dump('validationData');

        $this->merge([
            'foo' => 'bar',
        ]);

        return $this->all();
    }

    protected function rules()
    {
        dump('rules');

        dump($this->all());

        return [];
    }
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions