Como faço para acessar um membro no Twig determinado por uma variável?
Pergunta
Desejo fazer o seguinte código:
{% set rooms = [] %}
{% set opts = {
'hasStudio': 'Studio',
'has1Bed': '1 BR',
'has2Bed': '2 BR',
'has3Bed': '3 BR',
'has4BedPlus': '4 BR+'
}
%}
{% for key, val in opts %}
{% if bldg.{key} is none %} {# PROBLEM HERE.. HOW TO FIND THIS MEMBER!? #}
{{ val }}?
{% elseif bldg.{key} %}
{{ val }}
{% else %}
No {{ val }}
{% endif %}
{% endfor %}
Como faço para chamar as propriedades do membro de bldg que são nomeadas pelo valor de key
?Eu quero obter os valores de
bldg.hasStudio
bldg.has1Bed
bldg.has2Bed
etc....
Solução 2
Eu escrevi minha própria extensão twig para fazer isso.Você o usaria da maneira que eu quisesse:
{% set keyVariable = 'propertyName' %}
{{ obj.access(keyVariable) }}
{# the above prints $obj->propertyName #}
Aqui está:
// filename: Acme/MainBundle/Extension/AccessTwigExtension.php
namespace Acme\MainBundle\Extension;
class AccessTwigExtension extends \Twig_Extension
{
public function getFilters()
{
return array(
'access' => new \Twig_Filter_Method($this, 'accessFilter'),
);
}
public function getName()
{
return 'access_twig_extension';
}
// Description:
// Dynamically retrieve the $key of the $obj, in the same order as
// $obj.$key would have done.
// Reference:
// http://twig.sensiolabs.org/doc/templates.html
public function accessFilter($obj, $key)
{
if (is_array($obj)) {
if (array_key_exists($key, $obj)) {
return $obj[$key];
}
} elseif (is_object($obj)) {
$reflect = new \ReflectionClass($obj);
if (property_exists($obj, $key) && $reflect->getProperty($key)->isPublic()) {
return $obj->$key;
}
if (method_exists($obj, $key) && $reflect->getMethod($key)->isPublic()) {
return $obj->$key();
}
$newKey = 'get' . ucfirst($key);
if (method_exists($obj, $newKey) && $reflect->getMethod($newKey)->isPublic()) {
return $obj->$newKey();
}
$newKey = 'is' . ucfirst($key);
if (method_exists($obj, $newKey) && $reflect->getMethod($newKey)->isPublic()) {
return $obj->$newKey();
}
}
return null;
}
}
Para usá-lo em meu programa, também tive que adicionar algumas linhas à minha injeção de dependência:
//filename: Acme/MainBundle/DependencyInjection/AcmeMainInjection.php
// other stuff is here....
public function load(array $configs, ContainerBuilder $container)
{
// other stuff here...
$definition = new Definition('Lad\MainBundle\Extension\AccessTwigExtension');
$definition->addTag('twig.extension');
$container->setDefinition('access_twig_extension', $definition);
// other stuff here...
Outras dicas
Resposta curta: não é direta / nativamente possível ... ainda.
Aparentemente, eles adicionaram uma nova função ao Twig 1.2 chamada attribute () que atende exatamente a essa necessidade.
Mas até hoje você só pode baixar o Twig 1.1.2; então 1.2 provavelmente não é fornecido com SF2 - embora eu não consiga encontrar um número de versão. (1.2 já está disponível!)
Tentei resolver isso com vários truques, mas sem sucesso; 1.2 vai consertar isso.
Novo na versão 1.2: a função de atributo foi adicionada no Twig 1.2.
O atributopode ser usado para acessar um atributo “dinâmico” de uma variável:
{{ attribute(object, method) }}
{{ attribute(object, method,arguments) }}
{{ attribute(array, item) }}
Mas o que você pode fazer é adicionar um método à sua classe que cuida de tudo que você precisa. algo assim:
php :
class C
{
public $a = 1;
public $b = 2;
public function getValueForKey($k)
{
return $this->$k;
}
}
[ providing an instance of C to the template as 'obj' ]
galho :
{% set x = "a" %}
{{ obj.getValueForKey(x) }}
produzirá '1'
Use a sintaxe de colchetes: bldg[key]