Elemento de configuración de matriz de Twig

125

¿Cómo puedo establecer un miembro de una matriz ya existente de Twig?

Intenté hacerlo de la siguiente manera:

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

pero recibí el siguiente error:

Token inesperado "puntuación" del valor "[" ("fin del bloque de declaración" esperado) en ...

falinsky
fuente

Respuestas:

210

No hay una buena manera de hacer esto en Twig. Sin embargo, es posible utilizando el filtro de fusión:

{% set arr = arr|merge({'element': 'value'}) %}
Pablo
fuente
"." - la declaración es la misma que "[]", así que no es la solución
falinsky
@falinsky Tienes razón. .y []son muy similares en Twig y me equivoqué. Lo busqué y edité mi respuesta.
Paul
17
Estaba buscando una manera de definir la clave de variable dinámica en reemplazo de 'element'. Encontré la respuesta de @ LivaX a continuación. Entonces, lo sería {% set arr = arr|merge({(key): 'value'}) %}.
Sithu
Esto es muy tonto. ¿Por qué Twig no permite la capacidad de establecer valores de matriz?
Matt Cavanagh el
1
@MattCavanagh debido a que no se supone que los archivos de vista (como Twig) contengan lógica de negocios, esto debería manejarse en el modelo. Se supone que la vista simplemente representa lo que hay allí. Sin embargo, el problema en mi caso, y por qué también estoy de acuerdo con usted, es que creo macros de ramitas para representar objetos de la interfaz de usuario, por ejemplo. {{ UI.button({'type':'submit'}) }}y todas estas macros usan | fusionar para establecer los parámetros predeterminados, por lo que existe una necesidad lógica de esto ...
Prof83
79

Me encontré con este problema pero estaba tratando de crear índices enteros en lugar de índices asociativos como 'elemento'.

También debe proteger su clave de índice ()utilizando el filtro de combinación:

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

Ahora puede agregar una clave de índice personalizada como ('element'~loop.index0)

LivaX
fuente
Esa es la solución real cuando intentas insertar claves dinámicamente, ¡gracias LivaX!
nicolallias
19

Si la inicialización solo necesita:

{% set items = { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'unknown' } %}
pleerock
fuente
9
Esta no era la pregunta.
redreinard el
2

He intentado la respuesta de @LivaX pero no funciona, fusionar una matriz donde las teclas son numéricas no funcionará ( https://github.com/twigphp/Twig/issues/789 ).

Eso funcionará solo cuando las teclas sean cadenas

Lo que hice fue recrear otra tabla ( temp) de la tabla inicial ( t) y convertir las teclas en una cadena, por ejemplo:

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

t teclas: 0, 1, 2 ..

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

zizoujab
fuente
Mismo problema, no hay solución hasta ahora.
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'%}

Gracias por este hilo: también pude crear una matriz con (loop.index0) y enviar a twig.

n8tron
fuente
1

Este problema me pareció muy molesto, y mi solución es quizás ortodoxa y no está en línea con la filosofía Twig, pero desarrollé lo siguiente:

$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 se puede usar de la siguiente manera:

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

savedario
fuente
1

Simplemente use esto como {% set arr={'key':'value'} %}(sin espacio en blanco después de :), funciona bien.

Pero cuando lo uso dentro de un bucle for, para convertirlo en una matriz, no funciona fuera del alcance 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
usuario1321109
fuente
1
Si desea utilizar la variable fuera del ciclo for, debe definirla fuera del ciclo for, consulte aquí: twig.sensiolabs.org/doc/tags/set.html
user2019515
55
Esto es todo tipo de maldad. El espacio después del colon no importa. Está creando nuevas matrices, no configurando un elemento en la matriz que era la pregunta. No puede generar una matriz como {{array}}, eso generaría un error. Esta respuesta está llena de fallas y no está relacionada con la pregunta formulada.
redreinard el
3
No entiendo por qué esto tiene votos a favor, como se indicó anteriormente, casi todo es incorrecto en esta "respuesta" ...
MariusJP
0

Tenía una matriz multidimensional. La única solución que pude descubrir es crear una nueva matriz temporal y actualizar / agregar la información, que luego se pasó a otra función de ramita.

shobekhan
fuente
0

Tuve este problema hace algún tiempo. Imagina que tienes una 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'
}

Por lo tanto, desea mostrar estos datos en dos filas, pero elimine la contraseña de esa lista. Para este fin, dividir en 2 matrices será fácil con el slicefiltro. Sin embargo, tenemos que eliminar la contraseña. Por esa razón, estoy usando este fragmento. La idea es poner todos los elementos menores que el datatamaño de los elementos dividido por 2. Para calcular esto, usamos el filtro length. Ahora para obtener el índice del elemento actual que usamos loop.index. Y finalmente * empujamos un elemento asociativo en la matriz izquierda o derecha. Una matriz asociativa tiene dos componentes keyy value. Para hacer referencia a una clave de matriz en twit, operamos ()y usamos elmerge filtro filtro para insertarlo en la matriz como se muestra aquí{% set left_list = left_list|merge({ (key): value }) %}

Esta es la solución 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
fuente
0

También puede usar la siguiente sintaxis:

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