nova-flexible-content
nova-flexible-content copied to clipboard
How to use before and after rules on date fields?
How to use before and after rules on date fields?
none of this won't work
->rules('required', 'date', 'before:b_enddate'))
->rules('required', 'date', 'before:blackout.b_enddate'))
->rules('required', 'date', 'before:blackout.attributes.b_enddate))
The layout's unique identifier is blackout
and I have two fields b_startdate and b_enddate both is casted to date
Hi @vmihaly2020,
Layouts have their own (random) identifiers since one layout can have multiple instances. We'll have to check why before:b_enddate doesn't work, because it should.
Same issue with required_if, required_unless... all rules referencing another field.
Also, rules seems not applied if the value is null, example:
->rules(['nullable', new CustomRules]),
the CustomRules::passes() method is not called.
Here is how I fixed this for a required_with and a required_unless rule.
Create a new Layout class and use that one instead of Whitecube\NovaFlexibleContent\Layouts\Layout, then overwrite the getScopedFieldRules method.
use Whitecube\NovaFlexibleContent\Http\ScopedRequest;
use Whitecube\NovaFlexibleContent\Layouts\Layout as BaseLayout;
class Layout extends BaseLayout
{
/**
* Get validation rules for fields concerned by given request
*
* @param \Laravel\Nova\Fields\Field $field
* @param ScopedRequest $request
* @param null|string $specificty
* @param string $key
* @return array
*/
protected function getScopedFieldRules($field, ScopedRequest $request, $specificty, $key)
{
$method = 'get' . ucfirst($specificty) . 'Rules';
$rules = call_user_func([$field, $method], $request);
return collect($rules)->mapWithKeys(function ($validatorRules, $attribute) use ($key, $field) {
$rules = $this->wrapScopedFieldRules($field, $validatorRules);
// Scope the fields used in the rules
if ($rules !== null) {
foreach ($rules['rules'] as &$rule) {
if (substr($rule, 0, 16) === 'required_unless:') {
$rule = preg_replace('/^(required_unless:)(.+?)($|,.*$)/', '${1}' . $key . '.attributes.' . '${2}${3}', $rule);
} elseif (substr($rule, 0, 14) === 'required_with:') {
$rule = preg_replace('/^(required_with:)(.+)$/', '${1}' . $key . '.attributes.' . '${2}', $rule);
}
}
}
return [$key . '.attributes.' . $attribute => $rules];
})
->filter()
->all();
}
}
This works great.
Would you accept this feature into the codebase? It should be expanded with support for other rules like required_if, and account for Rule objects and such, but with a bit of polishing this would be a great addition to the core.
this is my solution for other rules in chosten's solution, the only problem is that the error message contains "content.0.attributes." in the string, dont know how to solve that yet, apart from that the logic works as it should:
protected function getScopedFieldRules($field, ScopedRequest $request, $specificty, $key)
{
$method = 'get' . ucfirst($specificty) . 'Rules';
$rules = call_user_func([$field, $method], $request);
return collect($rules)->mapWithKeys(function ($validatorRules, $attribute) use ($key, $field, $request) {
$rules = $this->wrapScopedFieldRules($field, $validatorRules);
if ($rules !== null) {
foreach ($rules['rules'] as &$rule) {
$ruleType = explode(':', $rule)[0];
$rule = preg_replace('/^(' . preg_quote($ruleType, '/') . ':)(.+)$/', '${1}' . $key . '.attributes.' . '${2}', $rule);
}
}
return [$key . '.attributes.' . $attribute => $rules];
})
->filter()
->all();
}