使用 Symfony 2.8 生成表单会引发Twig_Error_Runtime

2022-08-30 16:39:40

自从Symfony的最后一个LTS版本在几天前(30.11.2015)发布以来,我开始使用它。不幸的是,我无法使用与Symfony 2.7.7中正常工作的相同代码生成具有写入操作的CRUD。

首先,我使用Linux Mint 17.2下创建一个新的Symfony项目:bash

symfony new tasks lts

新目录是在内部使用新的 Symfony 2.8.0 项目创建的。tasks

在 I 中创建数据库调整数据库凭据后:app/config/parameters.yml

app/console doctrine:database:create

并生成一个新的捆绑包:

app/console generate:bundle --namespace=Acme/TasksBundle --format=yml

然后,我创建一个新目录,并在其中放置两个模型文件。这些是:src/Acme/TasksBundle/Resources/config/doctrine

Task.orm.yml

Acme\TasksBundle\Entity\Task:
    type: entity
    repositoryClass: Acme\TasksBundle\Repository\TaskRepository
    table: task
    id:
        id:
            type: integer
            generator: { strategy : AUTO }
    fields:
        description:
            type: text
    manyToMany:
        tags:
            targetEntity: Tag
            inversedBy: tasks
            cascade: [ "persist" ]
            joinTable:
                name: task_tag
                joinColumns:
                    task_id:
                        referencedColumnName: id
                inverseJoinColumns:
                    tag_id:
                        referencedColumnName: id

Tag.orm.yml

Acme\TasksBundle\Entity\Tag:
    type: entity
    repositoryClass: Acme\TasksBundle\Repository\TagRepository
    table: tag
    id:
        id:
            type: integer
            generator: { strategy : AUTO }
    fields:
        name:
            type: string
            length: 50
    manyToMany:
        tasks:
            targetEntity: Task
            mappedBy: tags

数据库架构应如下所示:

+----------------+     +--------------+
| task           |     | task_tag     |     +---------+
+----------------+     +--------------+     | tag     |
|   id           |<--->|   task_id    |     +---------+
|   description  |     |   tag_id     |<--->|   id    |
+----------------+     +--------------+     |   name  |
                                            +---------+

现在我可以生成实体:

app/console generate:doctrine:entities AcmeTasksBundle

这工作正常,因此可以更新数据库:

app/console doctrine:schema:update --force

到目前为止,一切都还好。这些表位于数据库中。现在我想使用写入操作生成 CRUD:

app/console generate:doctrine:crud --entity=AcmeTasksBundle:Task --with-write --format=yml

确认几个问题后,它会生成CRUD并打印出来:

Generating the CRUD code: OK

然后抛出此错误:

[Twig_Error_Runtime]                                                                                    
Key "tags" for array with keys "id, description" does not exist in "form/FormType.php.twig" at line 29

将创建控制器,但不创建窗体。

生成不带写入选项的 CRUD 工作正常。相同的代码在Symfony 2.7.7中完美无缺。

我检查了版本之间文件的差异,以下是相关部分:form/FormType.php.twig

Symfony 2.7.7
vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/skeleton/form/FormType.php.twig

{%- if fields|length > 0 %}
/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
    {%- for field in fields %}

        ->add('{{ field }}')
    {%- endfor %}

    ;
}
{% endif %}

Symfony 2.8.0
vendor/sensio/generator-bundle/Resources/skeleton/form/FormType.php.twig

{%- if fields|length > 0 %}
/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder

    {%- for field in fields -%}
        {%- if fields_mapping[field]['type'] in ['date', 'time', 'datetime'] %}

        ->add('{{ field }}', '{{ fields_mapping[field]['type'] }}')

        {%- else %}

        ->add('{{ field }}')

        {%- endif -%}
    {%- endfor %}

    ;
}
{% endif %}

正如我所看到的,for 循环中的 if 条件是发生错误的地方。(我假设表达式会导致问题,因为多对多字段()没有属性。fields_mapping[field]['type']tagtype

我做错了什么?我该如何解决这个问题?非常感谢您的帮助。

编辑:同样的问题发生在Symfony 3.0.0。该文件自版本 2.8 起已更改。form/FormType.php.twig


答案 1

看起来像生成器捆绑包中日期时间修复后的回归。

一个快速的解决方案是在 :composer.json

"sensio/generator-bundle": "^2.5",

最好的解决方案是分叉存储库,修复错误并创建一个拉取请求以回馈社区。

由于您已经完成了所有工作来隔离该错误,因此修复是微不足道的:检查中是否存在。类似的东西typeResources/skeleton/form/FormType.php.twig

{%- if fields_mapping[field]['type'] is defined and fields_mapping[field]['type'] in ['date', 'time', 'datetime'] %}

除非 Bug 基于相同的假设掩盖了更多隐藏的错误。


答案 2

我正在研究一下,并试图调试错误。

正如我上面提到的,自2.8.0版本以来,该文件已被更改。form/FormType.php.twig

显然,Symfony的制造者想要增强表单并自动解析类型,和。这发生在以下行中:datetimedatetime

{%- if fields_mapping[field]['type'] in ['date', 'time', 'datetime'] %}

这应该在阵列的帮助下实现。fields_mapping

通过一些快速而肮脏的解决方法,我试图找出 隐藏在 .这是我的模型的结果:fields_mapping

任务

{
    id => {
        id => 1,
        fieldName => id,
        type => integer,
        columnName => id
    },
    description => {
        fieldName => description,
        type => text,
        columnName => description
    }
}

循环访问 Task 的字段时,在最后一步中,它将遍历字段 。if 子句中的表达式如下所示:tags

fields_mapping['tags']['type']

正如我们在前面的示例中看到的,在 task 中没有键,只有 和 。由于该密钥不存在,因此将引发错误。tagsfields_mappingiddescriptiontags

我将文件中的相关行更改为如下所示:form/FormType.php.twig

{%- if fields_mapping[field] is defined and fields_mapping[field]['type'] in ['date', 'time', 'datetime'] %}

现在,我们可以使用新功能,并通过检查数组中是否存在密钥来防止错误。

我不知道这是否是一个错误,或者在我的特定情况下有什么问题。现在距离2.8.0和3.0.0版本发布已经过去了一周,所以可能有成千上万的用户一直在玩它们。我简直不敢相信,如果这是一个错误,没有人会注意到这一点。

编辑:

我在GitHub上发布了一个问题:

https://github.com/sensiolabs/SensioGeneratorBundle/issues/443

这是一个错误,已经以同样的方式解决了,正如我上面所想和写的那样:

https://github.com/Maff-/SensioGeneratorBundle/commit/205f64e96a94759f795271cb00fc86fb03b1fd4a


推荐