Repository navigation
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. Edit: changed on 891cd8f |
|
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('|');
}
} |
|
#56405 (comment) -> Don't you think we are overcomplicating it? I feel the same here - #56405 (comment) - but I understand we might want to refactor my code somehow. |
|
I can see why you think that. In the end, it comes down to what someone sees as complicated: Redundant but expressive code or compact code with a lot of indirection ("magic"). I'd say, both have their respective valid arguments. |
Yeah that's exactly what I think |
|
Fingers crossed! :) |
|
Don't think I'm going to pursue this right now but will probably explore cleaner validation in Laravel 13. |
#56346 (comment)
So lets go with all!