How to check for parameter not defined/not set in twig route?

131 Views Asked by At

I am working with symfony5/twig and I want to highlight a menu item when it's active (the current route).

I'm checking for route parameter as below sample shows, but I have not found a way to deal with the case when no parameter is passed (it is optional).

The below code works fine as long as a route with parameter is used, but once the route with no parameter is used, an error is thrown when it tries to check the app.request.attributes.get('type').id since obviously the app.request.attributes.get('type') is null and hence has no property 'id'.

    <li>
        <a class="{% if app.request.get('_route') == 'app_support_case_new' and app.request.query.get('type') is not defined %}active{% endif %}" href="{{ path('app_support_case_new') }}">
            <span class="glyphicon glyphicon-plus glyphicon-plus" aria-hidden="true"></span> No topic
        </a>
    </li>
    <li>
        <a class="{% if app.request.get('_route') == 'app_support_case_new' and  app.request.attributes.get('type').id == 1 %}active{% endif %}" href="{{ path('app_support_case_new', {'type':1}) }}">
            <span class="glyphicon glyphicon-plus glyphicon-user" aria-hidden="true"></span> Staff <i class="glyphicon glyphicon-random opacity50"></i>
        </a>
    </li>
    <li>
        <a class="{% if app.request.get('_route') == 'app_support_case_new' and app.request.attributes.get('type').id == 2 %}active{% endif %}" href="{{ path('app_support_case_new', {'type':2}) }}">
            <span class="glyphicon glyphicon-shopping-cart" aria-hidden="true"></span> Order
        </a>
    </li>   

In php I would put an isset(app.request.attributes.get('type')) before it in the conditions, and it would stop checking there. But apparently, twig checks all the conditions regardless.

I've tried adding this: app.request.attributes.get('type') is defined and

such as

<li>
    <a class="{% if app.request.get('_route') == 'app_support_case_new' and app.request.attributes.get('type') is defined and app.request.attributes.get('type').id == 1 %}active{% endif %}" href="{{ path('app_support_case_new', {'type':1}) }}">
        <span class="glyphicon glyphicon-plus glyphicon-user" aria-hidden="true"></span> Staff <i class="glyphicon glyphicon-random opacity50"></i>
    </a>
</li>

But it doesn't help. The error is still:

Impossible to access an attribute ("id") on a null variable.

<a class="{% if app.request.get('_route') == 'app_support_case_new' and app.request.attributes.get('type') is defined and app.request.attributes.get('type').id == 1 %}active{%endif %}" href="{{ path('app_support_case_new', {'type':1}) }}">
1

There are 1 best solutions below

0
DarkBee On

For this use-case you can simply use the filter default

{% if app.request.get('_route') == 'app_support_case_new' and app.request.attributes.get('type')|default == 1 %}active{% endif %}

FYI: The test defined doesn't take in account nullable values and behaves different than doing isset in PHP. That is because the test defined uses array_key_exists in the background. See snippet below

// line 2
echo ((array_key_exists("foo", $context)) ? (1) : (0));
{% set foo = null %}
{{ foo is defined ? 1 : 0 }} {# 1 #}
{{ foo ? 1 : 0 }} {# 0 #}

{% set foo = false %}
{{ foo is defined ? 1 : 0 }} {# 1 #}
{{ foo ? 1 : 0 }} {# 0 #}

{% set foo = 0 %}
{{ foo is defined ? 1 : 0 }} {# 1 #}
{{ foo ? 1 : 0 }} {# 0 #}

demo

<?php
 
    $foo = null;
    echo (isset($foo) ? 1 : 0).PHP_EOL;
    echo ($foo ? 1 : 0).PHP_EOL;
     
    $foo = false;
    echo (isset($foo) ? 1 : 0).PHP_EOL;
    echo ($foo ? 1 : 0).PHP_EOL;
     
    $foo = 0;
    echo (isset($foo) ? 1 : 0).PHP_EOL;
    echo ($foo ? 1 : 0).PHP_EOL;
0
0
1
0
1
0

demo