-
Notifications
You must be signed in to change notification settings - Fork 11.5k
[12.x] Feat: add validation rule builders for all rules #56405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 12.x
Are you sure you want to change the base?
Conversation
- Implement individual rule classes for all validation rules - Rename ArrayRule to Arr for consistency - Add tests for new rule classes - Update Rule class to support new rule instances
For rules that only implement the On one hand, I feel it's easier to make the method grow if it's in its own class. But if the class has no extra methods and only returns a string, it probably makes more sense to return the string directly. Let me know if I should change it. |
Ah, sorry, marked my review as a duplicate because GitHub accidentally displayed it twice—now, I can't unhide it 😬 |
How would you do it? Can you give me an example, @shaedrich? |
Sure thing: class Rule
{
use Macroable;
+
+ const SIMPLE_RULES = [
+ 'accepted',
+ 'active_url',
+ 'ascii',
+ // …
+ ];
/**
* Get a can constraint builder instance.
// …
return $parser->explode(ValidationRuleParser::filterConditionalRules($rules, $data));
}
+
+ public function __call(string $method, array $arguments)
+ {
+ if (in_array($method, self::SIMPLE_RULES)) {
+ return $method;
+ }
+ }
} This could be extended with shortcuts to rule classes: public function __call(string $method, array $arguments)
{
if (in_array($method, self::SIMPLE_RULES)) {
return $method;
- }
+ } else if (class_exists(($ruleClass = __NAMESPACE__ . '\\Rules\\' . Str::studly($method)))) {
+ return new $ruleClass;
+ }
} |
The abstract class AbstractRule
{
/**
* @var array<string, bool> $flags
*/
private array $flags = [];
/**
* @var array<string, null|scalar|scalar[]> $options
*/
private array $options = [];
public function __construct(...$arguments)
{
if (Arr::every($arguments, fn ($value, int|string $key) => is_string($key))) {
throw new InvalidArgumentException('Please use named arguments');
}
foreach ($arguments as $key => $value) {
if (array_key_exists($key, $this->options)) {
$this->options[$key] = array_unique([...$this->options[$key], $value]);
} else if (array_key_exists($key, $this->flags) && is_bool($value)) {
$this->flags[$key] = $value;
}
}
}
public function __call(string $method, array $arguments)
{
if (array_key_exists($method, $this->options) && count($arguments)) {
$this->options[$method] = array_unique(array_merge($this->options[$method], $arguments));
} else if (array_key_exists($method, $this->flags)) {
$this->flags[$method] = true;
}
}
public function __toString(): string
{
return collect([
Str::of(class_basename())->snake(),
...collect($this->flags)->filter()->keys(),
...collect($this->options)->filter()->map(fn ($value, string $key) => $key . ':' . (is_array($value) ? implode(',', $value) : $value)),
])->join('|');
}
} |
#56346 (comment)
So lets go with all!