【问题标题】:twig merge error Unexpected token "punctuation" of value "["树枝合并错误值“[”的意外标记“标点符号”
【发布时间】:2021-04-07 13:35:25
【问题描述】:

我的目标是有一个类似“名称:冰沙,成分:牛奶,橙子,类别:素食主义者”的字符串(可以有很多选项:值或选项:值,值,值...对)来生成数组如下

[
  {
     option: 'name',
     value: ['smoothie']
  },
  {
     option: 'ingredients',
     value: ['milk', 'orange']
  },
  {
     option: 'category',
     value: ['vegan']
  }
]

我认为像下面这样的东西会起作用,但它会产生以下错误,我不明白为什么。 问题出在我尝试向现有 options[last_ok_index].value 数组添加值的那一行

{% set options[last_ok_index].value = options[last_ok_index].value|merge( [ x[0] ] ) %}

值“[”的意外标记“标点符号”(应为“语句块结束”)。

{% set product = "name: smoothie, ingredients: milk, orange" %}
{% set options = [] %}
{% set last_ok_index = 0 %}
{% for item in product|split(',') %}
    {% set x = item|split(': ') %}
    {% if x|length == 2 %}
        {% set options = options|merge( [ { option: x[0], value: [x[1]] } ] ) %}
        {% set last_ok_index = loop.index - 1 %}
    {% else %}
        {% set options[last_ok_index].value = options[last_ok_index].value|merge( [ x[0] ] ) %}
    {% endif%}
{% endfor %}

{# print result #}
{% for item in options %}
    {{item.option }}
    {% for inner_item in item.value %}
        {{"-" ~ inner_item}}
    {% endfor %}
{% endfor %}

【问题讨论】:

  • 你为什么在模板而不是控制器或直接 PHP 中这样做?
  • 我不应该接触任何控制器代码......我相信在树枝中以某种方式是可能的
  • 您尝试过什么调试问题?为什么不逐步减少代码来发现问题呢?
  • 问题出在行 {% set options[last_ok_index].value = options[last_ok_index].value|merge( [ x[0] ] ) %} 所以当我尝试添加一个现有 options[last_ok_index].value 数组中的值
  • 您是否考虑过编写一个 TwigExtension 来处理解析字符串并返回数组?这样您就可以使用 PHP 而无需修改任何现有代码,例如在控制器中。您可以将此作为模板:stackoverflow.com/a/14504988/1166880

标签: php symfony merge twig


【解决方案1】:

您应该接受@dbrumann 在 cmets 中的建议,并使用 TwigExtension
但是,如果您想在纯 twig 中解决这个问题,那么您的事情就过于复杂了。

首先,问题已经从您的第一个split 开始,您的预期输出是smoothieingredients,而实际结果将是smoothieingredientsorange。您可以通过将第二个参数传递给 split 过滤器来解决此问题,这将限制输出。

Split 在后台使用PHP 函数explode。有关第二个参数的更多信息,您可以在文档here

中找到

现在正如我所说,您可以通过将“项目”分成两部分而不是一部分来创建您的 sn-p

{% set product = "name: smoothie, ingredients: milk, orange" %}

{% set items = [] %}

{% for item in product|split(',', 2) %}
    {% set tmp = item|split(':') %}
        
    {% set option = tmp[0] %}
    {% set values = [] %}
        
    {% for value in tmp[1]|split(',') %}
       {% set values = values|merge([ value, ]) %}
    {% endfor %}    
    
    {% set items = items|merge([ {'option': option, 'values': values,}, ]) %}
{% endfor %}

demo


由于您更改了原始问题的初始输入。问题仍然始于split 过滤器。我建议您使用另一个分隔符作为您的值,例如;

{% set product = 'name: smoothie 3, ingredients: milk ; orange; pineapple, category: bar' %}
{% set products = [] %}

{% for string in products_raw %}
    {% set product = [] %}
       
    {% for item in string|split(',') %}
        {% set tmp = item|split(':') %}
        
        {% set option = tmp[0] %}
        {% set values = [] %}
        
        {% for value in tmp[1]|split(';') %}
            {% set values = values|merge([ value, ]) %}
        {% endfor %}    
    
        {% set product = product|merge([ {'option': option, 'values': values,}, ]) %}
    {% endfor %}
    
    {% set products = products|merge([ product, ]) %}
{% endfor %}

{% for product in products %}
    {% for item in product %}
    - Option: {{ item.option }}
    - Values:
    {% for value in item.values %}
        - {{value }}
    {% endfor %}
{% endfor %}    
----------------------------------
{% endfor %}

demo

【讨论】:

  • 这不适用于以下字符串“名称:冰沙,成分:牛奶,橙子,饼干,类别:素食主义者”......也许我应该指定里面可能有许多选项值对字符串
  • 那是因为您更改了问题的输入。问题还是出在我刚才提到的问题上
  • 输入的模式是option: value, option: value, value, value, option: value, value....我觉得很明显是我的错....
  • 那么你需要改变你的输入模式,否则它永远不会起作用。查看我的编辑
  • 找到了一种在不改变模式的情况下让它工作的方法,尽管我明白我应该与有权改变模式的人交流。非常感谢您的回答
【解决方案2】:

非常感谢您提供的所有提示,我稍微更改了逻辑,现在它可以工作了。 我将按照您的建议搜索 twig 扩展,因为对于类似的东西来说,twig 中的代码肯定太多了。

{% set product = "name: smoothie, ingredients: milk, orange, sugar, tags: healthy, popular, category: milk" %}
{% set options = [] %}
{% set last_option = null %}
{% set last_value = null %}
{% for item in product|split(',') %}
    {% set x = item|split(':') %}
    {% if x|length == 2 %}
        {% if last_value|length > 0 %}
            {% set options = options|merge( [ {option: last_option, value: last_value} ] ) %}
        {% endif %}
        {% set last_option = x[0] %}
        {% set last_value = [x[1]] %}
    {% else %}
        {% set last_value = last_value|merge([x[0]]) %}
    {% endif%}
    {% if loop.last %}
        {% if last_value|length > 0 %}
            {% set options = options|merge( [ {option: last_option, value: last_value} ] ) %}
        {% endif %}
    {% endif %}
{% endfor %}

{# print result #}
{% for item in options %}
    {{ item.option }}
    {% for inner_item in item.value %}
        {{ "-" ~ inner_item }}
    {% endfor %}
{% endfor %}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-22
    • 2018-02-18
    • 2015-05-28
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多