Check if a variable is a date with Twig
Asked Answered
J

4

16

I have an array of variables that I want to display in a Twig template and each variable can be either a string or a date.

If the variable is a date, I want to apply the date filter like this:

{{ my_var|date('d/m/Y') }}

And if it's a string I want it to display it the usual way:

{{ my_var }}

Is there any way to test if a variable is a date (ie. an instance of the PHP DateTime object)?

Joannajoanne answered 23/1, 2013 at 14:34 Comment(4)
related issue on github: Consider an instanceof testMountebank
@DanLee Thanks, that's interesting but I understand why the PR has been closed without being merged as this would look like a kind of mix between PHP and Twig.Munos
Yes indeed, it's not really the business of the view. Thought it may help if you really wanted to implement the instanceof operator.Mountebank
See #10788638 where a test has been added in order to check the type of the variable.Buck
J
37

Maybe not the best way to do it, but I found a solution to my problem.

{% if my_var.timestamp is defined %}
    {{ my_var|date('m/d/Y') }}
{% else %}
    {{ my_var }}
{% endif %}

As a DateTime PHP object has a public getTimestamp method, it's a way to check if the variable is a date whether this property is set or not.

Joannajoanne answered 23/1, 2013 at 14:42 Comment(6)
+1 I'd say thats a perfectly fine way to do it, you'd need some sort of conditional statement somewhere unless you wanted to create a twig extensionKelleher
You could try to call date() like: date(my_var) ? my_var|date('d/m/Y') : my_var.Impertinence
The 'is defined' part is called a Test in Twig. Perhaps you could add your own called a_date, and do something like {% if my_var is a_date %} ...?Lewls
@Impertinence I dont think that'd work, I think you'll get an error. This should work ok though: {{ my_var.timestamp is defined ? my_var|date : my_var }}Kelleher
@Kelleher yep just ran some tests and it doesn't work...the timestamp is definitely a solution!Impertinence
Beware: twig date filter (kind of) gracefully degrades, rather than failing. It didn't fail for any of these input (´'2'´, ´'0'´, ´true´, ´false´, ´''´, ´' '´, ´not_exist´) but it gave unexpected results instead.Agamogenesis
P
7

Michael's solution works in most cases, but there are some special cases you should consider when you want to have a universal solution.

First, an object that you test for having a getTimestamp() method doesn't have to be a DateTime instance. I can thing of many cases when the timestamp field would be useful in an object, so I would test the getTimezone() method instead.

Second, if my_var is an object having a magic __call method defined, then all such tests would turn out positive. That's why I suggest the following negative test:

{% if my_var.timezone is defined and my_var.nonExistingProperty is not defined %}
    {{ my_var|date('m/d/Y') }}
{% else %}
    {{ my_var }}
{% endif %}

The second case was the one I recently struggled with because of using Propel ORM objects. The base class has the __call method that catches all Twig is defined tests.

Panel answered 21/2, 2014 at 17:51 Comment(0)
I
3

You could add a class(my_var) function, for example:

// src/AppBundle/Twig/HelperExtension.php

namespace AppBundle\Twig;

use Twig_Extension;
use Twig_SimpleFunction;

class HelperExtension extends Twig_Extension
{
    public function getFunctions()
    {
        return array(
            new Twig_SimpleFunction('class', array($this, 'getClassName')),
        );
    }

    public function getClassName($object)
    {
        if (!is_object($object)) {
            return null;
        }
        return get_class($object);
    }
}

Usage:

{% if class(my_var) == 'DateTime' %}
    ...
{% endif %}
Interplead answered 6/6, 2018 at 13:39 Comment(0)
F
2

This works for me

{% if myDate is instanceof('\DateTime') %}
Fiasco answered 24/8, 2022 at 13:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.