Как проверить многомерный массив 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 %}
видео
Я нашел себе решение. Не ожидал, что все будет так просто. Иногда я просто пытаюсь все усложнить.
{% 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