Elemento de configuração da matriz do Twig

125

Como definir membro de uma matriz já existente do Twig?

Eu tentei fazer da próxima maneira:

{% set arr['element'] = 'value' %}

mas eu recebi o seguinte erro:

Token inesperado "pontuação" do valor "[" ("fim do bloco de instruções" esperado) em ...

falinsky
fonte

Respostas:

210

Não há uma maneira legal de fazer isso no Twig. No entanto, é possível usando o filtro de mesclagem:

{% set arr = arr|merge({'element': 'value'}) %}
Paulo
fonte
"" - declaração é o mesmo que '[]', então não é a solução
falinsky
@falinsky Você está certo. .e []são muito parecidos em Twig e eu estava errado. Eu procurei e editei minha resposta.
Paul
17
Eu estava procurando uma maneira de definir chave de variável dinâmica em substituição de 'element'. Encontrei a resposta do @ LivaX abaixo. Então seria {% set arr = arr|merge({(key): 'value'}) %}.
Sithu
Isso é tão bobo. Por que o galho não permite a capacidade de definir valores de matriz?
precisa
1
@MattCavanagh porque os arquivos de exibição (como Twig) não devem conter lógica de negócios, isso deve ser tratado no modelo. A visão realmente deve simplesmente renderizar o que está lá. A questão, no entanto, no meu caso, e por que eu também concordo com você, é que eu crio macros de galho para renderizar objetos da interface do usuário, por exemplo. {{ UI.button({'type':'submit'}) }}e todas essas macros usam | mesclagem para definir parâmetros padrão, portanto, há uma necessidade lógica para isso ...
Prof83
79

Corri para esse problema, mas estava tentando criar índices inteiros em vez de índices associativos como 'elemento'.

Você também precisa proteger sua chave de índice ()usando o filtro de mesclagem:

{% set arr = arr|merge({ (loop.index0): 'value'}) %} 

Agora você pode adicionar uma chave de índice personalizada, como ('element'~loop.index0)

LivaX
fonte
Essa é a solução real quando você tenta inserir chaves dinamicamente, graças ao LivaX!
nicolallias 12/01
19

Se a inicialização precisar apenas:

{% set items = { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'unknown' } %}
pleerock
fonte
9
Esta não era a questão.
Redreinard 4/11
2

Tentei a resposta do @LivaX, mas ela não funciona, mesclando uma matriz em que as chaves numéricas não funcionam ( https://github.com/twigphp/Twig/issues/789 ).

Isso funcionará apenas quando as chaves forem strings

O que fiz foi recriar outra tabela ( temp) da tabela inicial ( t) e transformar as chaves em uma string, por exemplo:

{% for key , value in t%}
{% set temp= temp|merge({(key~'_'):value}) %}
{% endfor %}

t teclas: 0, 1, 2 ..

temp teclas: 0_, 1_, 2_ ....

zizoujab
fonte
Mesmo problema, nenhuma solução até agora.
TyrionGraphiste
2
{% set links = {} %}

{# Use our array to wrap up our links. #}
{% for item in items %}
  {% set links = links|merge({ (loop.index0) : {'url': item.content['#url'].getUri(), 'text': item.content['#title']} }) %}
{% endfor %}

{%
set linkList = {
  'title': label,
  'links': links
}
%}

{% include '<to twig file>/link-list.twig'%}

Obrigado por esta discussão - eu também fui capaz de criar uma matriz com (loop.index0) e enviar para o galho.

n8tron
fonte
1

Achei esse problema muito irritante, e minha solução talvez seja ortodoxa e não esteja de acordo com a filosofia Twig, mas desenvolvi o seguinte:

$function = new Twig_Function('set_element', function ($data, $key, $value) {
    // Assign value to $data[$key]
    if (!is_array($data)) {
        return $data;
    }
    $data[$key] = $value;
    return $data;
});
$twig->addFunction($function);

que pode ser usado da seguinte maneira:

{% set arr = set_element (arr, 'elemento', 'valor')%}

savedario
fonte
1

Basta usar isso como {% set arr={'key':'value'} %}(sem espaço em branco após o :), ele funciona bem.

Mas quando eu o uso dentro de um loop for, para torná-lo um array, ele não funciona fora do escopo for.

{% for group in user.groups %}
  {% set foo={'loop.index0':'group.id'} %}
  {% set title={'loop.index0':'group.title'} %}
  {{ title }} //it work 
{% else %}
  {% set foo={'0':'-1'} %}
  {% set title={'0':'未分组'} %}
{% endfor %}
{{ title }}  //it does not work, saying title is not defined
user1321109
fonte
1
Se você quiser usar a variável fora do loop for, precisará defini-la fora do loop for, veja aqui: twig.sensiolabs.org/doc/tags/set.html
user2019515
5
Isso é todo tipo de erro. O espaço após o cólon não importa. Você está criando novas matrizes, não definindo um elemento na matriz que foi a questão. Você não pode gerar uma matriz como {{array}}, que geraria um erro. Esta resposta está cheia de falhas e não está relacionada à pergunta.
Redreinard 4/11
3
Eu não entendo por que isso tem upvotes, como dito acima, quase tudo está incorreta neste "resposta" ...
MariusJP
0

Eu tinha uma matriz multidimensional. A única solução que eu pude descobrir é criar uma nova matriz temporária e atualizar / adicionar as informações, que foram repassadas para outra função de ramificação.

shobekhan
fonte
0

Eu tive esse problema há algum tempo. Imagine que você tem uma matriz como esta:

data = {
    'user': 'admin',
    'password': 'admin1234',
    'role': 'admin',
    'group': 'root',
    'profile': 'admin',
    'control': 'all',
    'level': 1,
    'session': '#DFSFASADASD02',
    'pre_oa': 'PRE-OA',
    'hepa_oa': 'HEPA-OA',
    'pre_ra': 'HEPA-RA',
    'hepa_ra': 'HEPA-RA',
    'deodor_ra': 'DEODOR-RA'
}

Portanto, você deseja mostrar esses dados em duas linhas, mas remova a senha dessa lista. Para isso, dividir em duas matrizes será fácil com o slicefiltro. No entanto, temos que remover a senha. Por esse motivo, estou usando esse trecho. A idéia é colocar todos os elementos menores que o datatamanho dos elementos dividido por 2. Para calcular isso, usamos o filtro length. Agora, para obter o índice do elemento atual que utilizamos loop.index. E, finalmente, pressionamos um elemento associativo na matriz esquerda ou direita. Uma matriz associativa possui dois componentes keye value. Para referenciar uma chave de matriz no twit we operator ()e usamos o mergefiltro para empurrar para dentro da matriz, como mostrado aqui{% set left_list = left_list|merge({ (key): value }) %}

Esta é a solução completa.

{% set left_list = {} %}
{% set right_list = {} %}
{% set limit = data|length // 2 %}
{% for key, value in data|cast_to_array %}
{% if key != 'password' %}
{% if loop.index <= limit %}
{% set left_list = left_list|merge({ (key): value }) %}
{% else %}
{% set right_list = right_list|merge({ (key): value }) %}
{% endif %}
{% endif %}
{% endfor %}
{% for key, value in left_list %}
<p>
<label for="{{key}}">{{key}}</label>
<input type="text" name="{{key}}" id="{{key}}" value="{{value}}"
       class="text ui-widget-content ui-corner-all">
</p>
{% endfor %}
Teocci
fonte
0

Você também pode usar a seguinte sintaxe:

{% set myArray = myArray + myArray2 %}
GarryOne
fonte