1

I have a form that lets you search articles by date.
The 'Results' template uses dates from the query string in an Entries Query like this:

{% set afterParam = craft.app.request.getQueryParam('after') %}
{% if afterParam is not empty %}
  {% set entriesQuery = entriesQuery.after(afterParam) %}
{% endif %}

I'd like to avoid errors when a date is invalid... but I can't find a simple, bullet-proof way to validate.
I can use a regex to check each date parameter looks like YYYY-MM-DD:

{% if dateParam matches '/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/' %}
...

But this doesn't stop strings like '2022-13-01' getting through (here, the invalid Month causes a Database Exception).
Does anyone know a straight-forward way to validate date strings in Twig?

1 Answer 1

1

Parse, don't validate. Instead of validating the format, which will get complicated fast, parse it as a date and see if it works or not.

The simplest solution is something like this:

{% set dateParam = craft.app.request.getQueryParam('after') %}
{% if afterParam is not empty %}
  {% set entriesQuery = entriesQuery.after(afterParam | date) %}
{% endif %}

This will throw an exception if the afterParam is not in any valid date format. In the production environment, this will result in a simple error page, which you can customize with a custom error template.

Now you may say that this is an unacceptable user experience, but it depends on what kind of interface you're presenting in the user face. What kind of input are you providing for the date parameter? If you use a native date input, the browser will display a date picker and will prevent users from entering an invalid date. You can also use JavaScript to catch invalid formats and prevent them from being sent to the server. So a regular user will never encounter the exception view, since the UX for validating date inputs is handled on the client-side – by the browser itself if you're using native date inputs. In this case, the server-side date parsing is about security, not user experience, so an exception is fine.

If you still want to handle invalid date formats gracefully, you can create a simple Twig test in a Twig extension that will try to parse the parameter as a date and returns true or false based on whether it succeeds:

public function getTests()
{
    return [
        new \Twig\TwigTest('valid_date', function($date) {
            try {
                $dateObj = new \DateTime($date);
                return true;
            } catch (\Exception $e) {
                return false;
            }
        }),
    ];
}

Now you can use it like this to check if the date param is valid:

{% set is_valid_date = dataParam is valid_date %}

You could also make this a function that either returns the DateTime object if the format is valid or null if it isn't. Then you can check the return value and only apply it to the query if it isn't null, and display and error message if it is.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.