Set value of single object in multidimensional arr

2019-01-12 08:05发布

问题:

For project needs I need to change some form fields data before they render. To do that I iterate over form elements and dynamically change values I need.

Problem is that I can't change value. I got this error:

Unexpected token "punctuation" of value "." ("end of statement block" expected).

I used this piece of code to change value but I got error above:

{% set arr = arr|merge({'element': 'value'}) %}

Does someone knows where is the problem?

This is code I used.

Twig template code (example code I used)

<ul>
        {% dump (edit_form) %}
        {% for element in edit_form.children %}
            {% dump (element.vars) %}
            {% set element.vars = element.vars|merge({'name': 'My title (just for testing purpose)'}) %}

            <li>{{ element.vars.name }}</li>
        {% endfor %}
    </ul>

Form object:

FormView {#637 ▼
  +vars: array:24 [▶]
  +parent: null
  +children: array:4 [▼
    "title" => FormView {#699 ▼
      +vars: array:24 [▼
        "value" => "le title"
        "attr" => []
        "form" => FormView {#699}
        "id" => "adminbundle_intro_title"
        "name" => "title"
        "full_name" => "adminbundle_intro[title]"
        "disabled" => false
        "label" => null
        "label_format" => "admin.intro.form.%name%"
        "multipart" => false
        "block_prefixes" => array:3 [▶]
        "unique_block_prefix" => "_adminbundle_intro_title"
        "translation_domain" => null
        "cache_key" => "_adminbundle_intro_title_text"
        "errors" => FormErrorIterator {#696 ▶}
        "valid" => true
        "data" => "le title"
        "required" => true
        "size" => null
        "label_attr" => []
        "compound" => false
        "method" => "POST"
        "action" => ""
        "submitted" => false
      ]
      +parent: FormView {#637}
      +children: []
      -rendered: false
    }
    "content" => FormView {#698 ▶}
    "isEnabled" => FormView {#702 ▶}
    "_token" => FormView {#711 ▶}
  ]
  -rendered: false
}

回答1:

To change a certain index of an array you're best of with extending Twig, a solution could be this,

ProjectTwigExtension.php

namespace Your\Namespace;

class ProjectTwigExtension extends Twig_Extension {

    public function getFunctions() {
        return array(
            new Twig_SimpleFunction('set_array_value', array($this, 'setArrayValue'), ['needs_context' => true,]),
            new Twig_SimpleFunction('set_object_property', array($this, 'setArrayValue'), ['needs_context' => true,]),      
        );      
    }

    public function setArrayValue(&$context, $array_name, $index, $value) {
        if (!isset($context[$array_name])) return;
        if (is_array($context[$array_name])) $context[$array_name][$index] = $value;                
        elseif(is_object($context[$array_name])) {
            if (method_exists($context[$array_name], $index)) $context[$array_name]->{$index}($value);
            elseif(method_exists($context[$array_name], 'set'.$index)) $context[$array_name]->{'set'.$index}($value);
        }
    }

    public function getName() {
        return 'ProjectTwigExtension';
    }        
}

Add extension to twig

$twig->addExtension(new \Your\Namespace\ProjectTwigExtension());
/** ... code ... **/
$user = new User();
$user->setUserName('admin');

$twig->render('template.twig', [ 'somearray' => ['foo' => 'bar',], 'user' => $user, ]);

template.twig

{{ dump(somearray) }} {# output: array(1) { ["foo"]=> string(3) "bar" } #}

{{ set_array_value('somearray', 'foo', 'foobar') }}

{{ dump(array) }} {# output: array(1) { ["foo"]=> string(6) "foobar" }  #}

{{ dump(user.getUserName()) }} {# output: string(5) "admin" #}

{{ set_object_property('user', 'UserName', 'StackOverflow') }}

{{ dump(user.getUserName()) }} {# output: string(13) "StackOverflow" #}