Skip to content
This repository has been archived by the owner on Sep 9, 2019. It is now read-only.

[WIP] Rules #108

Closed
wants to merge 12 commits into from
Closed

[WIP] Rules #108

wants to merge 12 commits into from

Conversation

viktorprogger
Copy link
Contributor

@viktorprogger viktorprogger commented Nov 30, 2018

Q A
Is bugfix? no
New feature? no
Breaks BC? yes
Tests pass? no
Fixed issues #96

Here is an example of my vision about how it should work. I've changed NumberValidator instead of abstract Validator to simplfy this example. If all is ok, I'll change all the core validators and the relevant tests.

@samdark
Copy link
Member

samdark commented Dec 1, 2018

@miolae any usage syntax examples?

@viktorprogger
Copy link
Contributor Author

@samdark Usage axample

$validator = new NumberValidator();
$validator->attributes = $this->getAttributesForValidator();
$validator->min(1);

return [
    [['login', 'pass'], (new NumberValidator())->min(6)->max(255)],
   $validator,
];

I'd prefer a more convenient way to set attributes, but I didn't find it globally in the system.

@viktorprogger
Copy link
Contributor Author

I've read the issue again and I'm confused. There is also a good variant $this->property => Validator::number()->min(9)->required().

But there could be some difficulties with equal keys (when property1 and property2 has the same value but different validators).

On the other hand the right part is looking very tasty. I can add some code to implement this. Because now there is no way to set several validators to a single set of attributes (I understood it just now).

@samdark
Copy link
Member

samdark commented Dec 3, 2018

Could be the following as well:

public function rules(Validator $is)
{
    return [
        [['name', 'email', 'subject', 'body'], $is->required()],
        ['email', $is->email()],
        [['login', 'pass'], $is->number()->min(6)->max(255)],
    ];
}

@viktorprogger
Copy link
Contributor Author

viktorprogger commented Dec 4, 2018

I think built-in and custom validator using shouldn't differ too much. You're now showing only built-in variant. And how will look a custom one?

@samdark
Copy link
Member

samdark commented Dec 4, 2018

Right. Then:

public function rules()
{
    return [
        [['name', 'email', 'subject', 'body'], new RequiredValidator()],
        ['email', new EmailValidator()],
        [['login', 'pass'], (new NumberValidator())->min(6)->max(255)],
        ['branch', new CustomBranchValidator()->primaryOnly()],
    ];
}

@viktorprogger
Copy link
Contributor Author

This variant is already realized for NumberValidator 👍

@samdark
Copy link
Member

samdark commented Dec 5, 2018

I think it's good enough. Let's do other validators and docs.

@samdark samdark added the type:enhancement Enhancement label Dec 5, 2018
@samdark samdark added this to the 3.0.0 milestone Dec 5, 2018
@viktorprogger viktorprogger changed the title #96 Rules [WIP] Rules Dec 24, 2018
@viktorprogger
Copy link
Contributor Author

viktorprogger commented Dec 25, 2018

@samdark (or anybody of yiisoft) make a code review please. There are some significant changes. I've described them in the changelog. If all is ok I'll continue with other validators (now only NumberValidator is completely rewritten).
Please pay attention also to the new test I've written. I will make an abstract test with this logic, if you like it, and rewrite other validation tests in a such way. The main idea is to check all available validation rules (see the changelog) combination with equal set of values to be completely sure that all validations are ok.

@@ -466,4 +542,48 @@ public function getAttributeNames()
return ltrim($attribute, '!');
}, $this->attributes);
}

private function ruleEsixts(string $name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exists*

@@ -448,8 +448,10 @@ public function createValidators()
foreach ($this->rules() as $rule) {
if ($rule instanceof Validator) {
$validators->append($rule);
} elseif (is_array($rule) && isset($rule[0], $rule[1])) { // attributes, validator type
$validator = Validator::createValidator($rule[1], $this, (array) $rule[0], array_slice($rule, 2));
} elseif (is_array($rule) && isset($rule[0], $rule[1]) && $rule[1] instanceof Validator) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for removing support for plain arrays with validator config? Looks like unnecessary BC break.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this configuration way is deprecated.

There was a discussion about this in Slack. Somebody said that the deprecation will be removed. So, I'll return arrays for configuration.

* @return mixed
* @throws InvalidConfigException
*/
public function __call($name, $params)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why rely on magic __call() and processing some constant with configuration? It is less flexible and less readable than regular getters and setters.

```php
public function rules() {
return [
[['login', 'pass'], (new NumberValidator())->min(6)->integerOnly(true)],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true could be default.

public function rules() {
return [
[['login', 'pass'], (new NumberValidator())->min(6)->integerOnly(true)],
['email', new RequiredValidator],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

() should be specified.

];
}
```
- Validators don't contain validation logic anymore. They are containers for _validation rules_ (see `BaseRule` class).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

- either with a given callback
- or with a given regular expression
- In all other cases you just need to extend `BaseRule` and change or add the needed bit of logic
- Validation rules themselves are described in the `RULES` constant of your validator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks like validator and its rule are coupled very tightly... is there a reason for these to be separate classes?

*
* @throws InvalidConfigException
*/
public function setRule(string $name, $value, ?string $message = null, $validation = null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason introducing such flexibility/complexity? While re-configuring rules and overriding standard ones is definitely cool, it may be easily abused to change standard predictable behavior. Are there use cases for it?

@viktorprogger
Copy link
Contributor Author

Thank you very much for your feedback. Now I have a lot of work in different directions and can't take time for this. A bit later I'll reconsider my decisions.

@viktorprogger
Copy link
Contributor Author

Will begin from draft with all requested changes.

@samdark
Copy link
Member

samdark commented May 22, 2019

@viktorprogger thank you for ideas. There's now https://github.com/yiisoft/validator

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants