3
votes

In the CakePHP 3 docs there's a section on Reusable Validators: https://book.cakephp.org/3.0/en/core-libraries/validation.html#creating-reusable-validators

It doesn't say how you use them, in a Controller though. Can anyone give an example?

I have a particular application which allows .csv files to be uploaded. The validation for a .csv file in the application is always the same: check it's MIME type, check the size, check the extension, etc.

So my plan was to implement this as a reusable validator - is that correct?

I have an UploadsController.php with an upload() function, which is where I want to use this to validate data coming from a form. I'm confused because I'm not creating an Entity at this point - but rather just trying to validate my file - so all this patchEntity() stuff in the docs makes no sense here.

I find the documentation on validation for Cake 3 very confusing, because there's a section under the ORM (https://book.cakephp.org/3.0/en/orm/validation.html) where it says

Validation rules are defined in the Table classes

But later on, it has a completely different section on validating Entities (https://book.cakephp.org/3.0/en/core-libraries/validation.html#validating-entities).

Then we have Reusable Validators..... and various other things.

Since Table and Entity model classes in Cake 3 differ, can someone explain how you would go about validating something like a file upload, particularly given that there may even be no table at all involved?

And what if you have a combination on a form where you need to use both a Reusable Validator (for a common task like validating a .csv), and also a separate set of rules for a specific table that might be in a Table model class?

1
Why do not you create an UploadComponent to Do all upload stuff, including validation?Rayann Nayran
@RayannNayran I'd like to understand how to use the Reusable Validators provided but can't see how to reference that in my Controller. At the moment my form submits to UploadsController:upload(). If I were to create src/Model/Validation/CsvValidator.php how so I then pass the form data to that, via UploadsController:upload() and get back the validation messages?Andy

1 Answers

6
votes

Tables supply the contract

It's actually not that complicated. Validation rules that concern tables are defined on tables for convenience. They don't have to be defined there, they can be defined in custom validation classes, but finally the table object supplies the requested validation rules set.

Validating entities is part of the common validation flow. Since entities are sets of data that are passed to tables, it's the tables that should hold the rules that decide whether an entity is valid or not, because that's the tables concern.

See also

Inherit validation rules

Combining validators is pretty easy, simply pass your custom validation object to the validation*() method in your table class that provides the rules that you want to inherit, something along the lines of:

public function validationDefault(Validator $validator)
{
    $validator
        ->add(/* ... */);

    return $validator;
}

public function validationCustomAndDefault()
{
    $validator = new \App\Model\Validation\CustomModelValidator();

    return $this->validationDefault($validator);
}

Then just configure the validate option as customAndDefault, and your data/entities are being validated with your custom validation object rules, and the default ones.

See also

Validation is not tied to the model layer

Besides that, validation is not tied to the mode layer, it just makes use of it, you can always use validation objects wherever you want, ie if you want to validate data manually, just instantiate a validator class and use it to validate your data:

$validator = new \App\Validation\CustomGenericValidator();
$errors = $validator->errors($data);

See also