Как проверить многомерный массив Twig на наличие значений?

чтобы просто проверить, содержит ли массив определенное значение, я бы сделал:

{% if myVar in someOtherArray|keys %}
...
{% endif %}

однако мой массив многомерен.

$tasks = array(
    'someKey' => 'someValue',
    ...
    'tags' => array(
        '0' => array(
            'id'   => '20',
            'name' => 'someTag',
        ),
        '1' => array(
            'id'   => '30',
            'name' => 'someOtherTag',
        ),
    ),
);

что я хотел бы, чтобы иметь возможность проверить, если $tasks['tags'] имеет идентификатор тега 20. Надеюсь, я не путаю вас, используя формат массива PHP.

6 ответов


установите флаг и используйте цикл. После этого вы можете использовать флаг, если условия.

{% set flag = 0 %}
{% for tag in tasks.tags %}
    {% if tag.id == "20" %}
        {% set flag = 1 %}
    {% endif %}
{% endfor %}
{{ flag }}

это больше похоже на многомерный цикл, если это необходимо

   {% for animals in array %}

        {% set dogs = animals.dogs %}

        {% for dog in dogs %}
            {{ dump(dog.type) }}
        {% endfor%}

    {% endfor %}

для оператора if внутри многомерного массива в Twig. Проверьте в for-loop, а затем оператор if.

вот стенография для этого с прутиком:

{% for tag in tasks.tags if tag.id == '20' %}      
       here_if_true
{% endfor %}    

- - - -редактировать ----

ДЛЯ ELSE

сделать else. Так что else вот если ничего не нашли во всем for:

{% for tag in tasks.tags %}    
       here_if_true
{% else %}
       if there was nothing found
{% endfor %}    

ДЛЯ-ЕСЛИ ЕЩЕ

сделать комбинация if и else возможно, но это не то же самое как if else внутри for петли. Потому что else на for а не if.

{% for tag in tasks.tags if tag.name == 'blue' %}      
    This will fire if in the FOR the tag.name that is blue
{% else %}
    This will fire if there were NO tag.name blue were found ENTIRE FOR!
{% endfor %}

видео

для - Если еще и если еще

{% for tag in tasks.tags if tag.id == 3 %}    
    the id is 3
    {% if tag.name == 'blue' %}
    the id of the tag is 3 and tag.name is blue
    {% else %} 
    the id of the tag is 3 but the tag.name is not blue
    {% endif %}
{% else %}
    there was no tag.id 3 found in the tasks.tags
{% endfor %}

видео

документация TWIG


Я нашел себе решение. Не ожидал, что все будет так просто. Иногда я просто пытаюсь все усложнить.

{% for tag in tasks.tags %}
    {% if tag.id == '20' %}
        This tag has ID 20
    {% endif %}
{% endfor %}

на мой взгляд, это не самый эффективный способ, но это делает трюк для меня на данный момент.

редактировать

Yenne Info сообщил мне о следующем методе. Немного чище. Я не знаю, улучшает ли это производительность.

{% for tag in tasks.tags if tag.id == '20' %}
    Bingo! We've got a match
{% endfor %}

установка флага в Twig

{% set flag = 0 %}

{% for tag in tasks.tags %}
    {% if tag.id == "20" %}
        {% set flag = 1 %}
    {% endif %}
{% endfor %}

{% if flag == 1 %}
    //do something
{% endif %}

создание Настраиваемый Фильтр в PHP

для уменьшения кода в ваших шаблонах веточка имеет возможность создавать пользовательские фильтры. Для достижения более общей функциональности вы можете просто использовать имена переменных переменных и использовать имя атрибута в качестве другого параметра.

PHP

$filter = new Twig_SimpleFilter('inTags', function ($tags, $needle) {
    $match = false;
    foreach($tags as $tag){
        if(in_array($needle, $tag)){
            $match = true;
            break;
        }
    }
    return $match;
});

$twig = new Twig_Environment($loader);
$twig->addFilter($filter);

веточка

{% if tasks.tags|inTags(20) %}
    //do something
{% endif %}

{% if myVar is xpath_aware('//tags/*[id=20]') %}

контекст

если вы собираетесь делать условия на произвольном глубоком массиве, почему бы не использовать силу xpath? Массив-это не более, чем необходимо выполнить десериализацию XML-строку в конце концов!

Итак, следующий массив:

$data = array(
    'someKey' => 'someValue',
    'foo'     => 'bar',
    'hello'   => array(
        'world' => true,
        'tags'  => array(
            '0' => array(
                'id'   => '20',
                'name' => 'someTag',
            ),
            '1' => array(
                'id'   => '30',
                'name' => 'someOtherTag',
            ),
        ),
    ),
);

является эквивалентом строки XML (исправлено, чтобы избежать числовых тегов):

<data>
    <someKey>someValue</someKey>
    <foo>bar</foo>
    <hello>
        <world>1</world>
        <tags>
            <item0>
                <id>20</id>
                <name>someTag</name>
            </item0>
            <item1>
                <id>30</id>
                <name>someOtherTag</name>
            </item1>
        </tags>
    </hello>
</data>

и вы хотите знать, соответствует ли Ваш массив следующему xpath выражение:

//tags/*[id=20]

реализация

мы создаем новый тест прутик это преобразует наш массив в SimpleXMLElement объект, и использовать SimpleXMLElement::xpath() чтобы проверить, соответствует ли данный xpath.

$test = new Twig_SimpleTest('xpath_aware', function (array $data, $path) {
    $xml = new SimpleXMLElement('<?xml version="1.0"?><data></data>');
    array_to_xml($data, $xml); // see full implementation below

    return array() !== $xml->xpath($path);
});

теперь мы можем запустить следующий тест в Twig:

{% if myVar is xpath_aware('//tags/*[id=20]') %}

полная исполняемая реализация:

xpath_test.в PHP

<?php

include (__DIR__.'/vendor/autoload.php');

$context = array(
    'myVar' => array(
        'someKey' => 'someValue',
        'foo'     => 'bar',
        'hello'   => array(
            'world' => true,
            'tags'  => array(
                '0' => array(
                    'id'   => '20',
                    'name' => 'someTag',
                ),
                '1' => array(
                    'id'   => '30',
                    'name' => 'someOtherTag',
                ),
            ),
        ),
    ),
);

// http://stackoverflow.com/a/5965940/731138
function array_to_xml($data, &$xml_data)
{
    foreach ($data as $key => $value) {
        if (is_array($value)) {
            if (is_numeric($key)) {
                $key = 'item'.$key; //dealing with <0/>..<n/> issues
            }
            $subnode = $xml_data->addChild($key);
            array_to_xml($value, $subnode);
        } else {
            $xml_data->addChild("$key", htmlspecialchars("$value"));
        }
    }
}

$twig = new Twig_Environment(new Twig_Loader_Array([]));

$test = new Twig_SimpleTest('xpath_aware', function (array $data, $path) {
    $xml = new SimpleXMLElement('<?xml version="1.0"?><data></data>');
    array_to_xml($data, $xml);

    return array() !== $xml->xpath($path);
});

$twig->addTest($test);

$source = <<< EOT
{% if myVar is xpath_aware('//tags/*[id=20]') %}
It matches!
{% endif %}
EOT;

$template = $twig->createTemplate($source);
echo $template->display($context);

запустить это

composer require twig/twig
php xpath_test.php