26

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

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

symfony new tasks lts

新目录tasks被创建,里面有一个新的 Symfony 2.8.0 项目。

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

app/console doctrine:database:create

并生成一个新包:

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

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

任务.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

标签.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']会导致问题,因为多对多字段 ( tag) 没有属性type。)

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

编辑:Symfony 3.0.0 也会出现同样的问题。该文件form/FormType.php.twig自 2.8 版以来已更改。

4

3 回答 3

17

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

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

显然 Symfony 的开发者想要增强表单并自动解析类型datetime并且datetime. 这发生在以下行中:

{%- 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 的字段时,在最后一步中遍历字段tags。if 子句中的表达式如下所示:

fields_mapping['tags']['type']

tags正如我们在前面的示例中看到的,fields_mappingfor Task中没有键,只有idand description。由于密钥tags不存在,因此会引发错误。

我将文件中的相关行更改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

于 2015-12-07T10:28:15.697 回答
17

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

一个快速的解决方案是恢复到 v2.* 在您的composer.json

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

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

由于您已经完成了隔离错误的所有工作,因此修复很简单:type检查Resources/skeleton/form/FormType.php.twig. 就像是

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

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

于 2015-12-07T10:15:05.140 回答
3

即使更新固定捆绑包后问题仍然存在,有时解决问题的最简单方法是删除vendor目录,并更新作曲家。

于 2015-12-14T15:27:23.003 回答