beberlei / assert

Thin assertion library for use in libraries and business-model
Other
2.41k stars 188 forks source link

Allow predicated validation in Lazy Assertions chains #317

Open ccybuszSV opened 3 years ago

ccybuszSV commented 3 years ago

The current Assert::lazy() is a very powerful tool that allows for clean easy validation in our actions. However, we've noticed that we sometimes come across this use case:

  1. A is a parameter that has many valid values (e.g. a number between 0 and 999 inclusive)
  2. B is a parameter that must be a valid email if A is greater than 0

As it stands, there's no "clean" way of doing this in one pass. It would require that a first Assert::lazy() be passed with all the validation that isn't predicated on a separate value. Then, a second Assert::lazy() must be assembled and verified after the first one. Having two sets of lazy assertions somewhat defeats its purpose. I imagine it could work something like this:

Assert::lazy()
    // validates $A and adds its validation to a lookup
    ->that($A, 'A', 'A must be between 0 and 999')->numeric()->min(0)->max(999) 

    // adds the evaluation of `$A > 0` to a validation lookup but does
    // not treat it as validation (i.e. if it's false, it won't fail at `verifyNow()`)
    ->evaluate($A, 'pA')->numeric()->greaterThan(0) 

    // asserts that $B is an email if `pA` is true, otherwise it skips (i.e. if
    // `$B` is not an email and `pA` is false, `verifyNow()` won't fail)
    ->that($B, 'B', 'B must be a valid email')->predicatedOn('pA')->email()
    ->verifyNow();

Ideally, some kind of collection of methods that create evaluations / predicate logic on previous validations would be neat but isn't needed to implement that behaviour! By providing a getter for the $currentChainFailed and a way to insert a AssertionFailedException object in the $errors array, one could extend LazyAssertion with predicate logic themselves!

Otherwise, ideally this feature should be implemented to cover what I imagine can be a significant number of cases. Thoughts?