Skip to content

Latest commit

 

History

History
53 lines (47 loc) · 2.5 KB

3_18.md

File metadata and controls

53 lines (47 loc) · 2.5 KB

3.18 The Range constraint on dates

Range accepts a date as well as a number. When the validated value is a \DateTimeInterface, Symfony reads a string bound through the PHP date parser, so both an absolute date and a relative expression are allowed:

class User
{
    #[Assert\Range(
        min: 'first day of this month - 14 years UTC',
        max: 'today',
    )]
    public ?\DateTimeInterface $birthday = null;
}
$builder->add('birthday', DateType::class);

The browser has no equivalent of that parser, so the bounds are resolved on the server while the form is rendered and exported as concrete dates. A DateType exports them as Y-m-d, a DateTimeType as Y-m-d H:i:s, and the JavaScript Range constraint compares the submitted value against them as a date instead of as a number. Absolute bounds are exported the same way, normalized to the format of the field.

Nothing has to be configured, but a few limits are worth knowing:

  • A relative bound is frozen when the page is rendered. max: 'today' becomes the day the form was built. A page left open across midnight validates against yesterday in the browser, and the server, which re-reads the bound on submit, has the last word. Reload the form, or use an absolute bound, where that matters.
  • TimeType is not covered. Its value carries a time only, while Symfony resolves a bound such as '10:00' to that time on the current day, so the two are not comparable. Bounds of a TimeType field are exported unchanged and the field keeps the previous behaviour.
  • The field must hold a date object. With 'input' => 'string', 'timestamp' or 'array' the model value is not a \DateTimeInterface, so Symfony compares it as a number and the bounds are exported unchanged.
  • The submitted value has to reach JavaScript as an ISO date. That is what the widgets of DateType and DateTimeType produce, including the HTML5 date and datetime-local inputs. A field rendered through DateTimeToLocalizedStringTransformer — a single text widget with 'html5' => false — submits a value formatted for the locale, which is reported with the invalidDateTimeMessage of the constraint.
  • Messages show the bound as the exported date string. Symfony formats it for the locale of the server instead.
  • A bound read from another field through minPropertyPath or maxPropertyPath (see Comparing a field with another field) is compared as a date as well, as soon as the referenced field holds one.