使用 Symfony 2.8 生成表单会引发 Twig_Error_Runtime
自从几天前(30.11.2015)发布了 Symfony 的最后一个 LTS 版本以来,我开始使用它.不幸的是,我无法使用在 Symfony 2.7.7 中运行良好的相同代码生成具有写入操作的 CRUD.
Since the last LTS version of Symfony was released few days ago (30.11.2015) I started playing with it. Unfortunately I can't generate a CRUD with write actions with the same code that works fine in Symfony 2.7.7.
首先我在 Linux Mint 17.2 下使用 bash
创建一个新的 Symfony 项目:
First I create a new Symfony project using the bash
under Linux Mint 17.2:
symfony new tasks lts
新目录 tasks
被创建,其中包含一个新的 Symfony 2.8.0 项目.
The new directory tasks
gets created with a new Symfony 2.8.0 project inside.
在 app/config/parameters.yml
中调整数据库凭据后,我创建了数据库:
After adapting the database credentials in app/config/parameters.yml
I create the database:
app/console doctrine:database:create
并生成一个新包:
app/console generate:bundle --namespace=Acme/TasksBundle --format=yml
然后我创建一个新目录 src/Acme/TasksBundle/Resources/config/doctrine
并在其中放置我的模型的两个文件.它们是:
Then I create a new directory src/Acme/TasksBundle/Resources/config/doctrine
and place two files for my models inside. These are:
Task.orm.yml
Task.orm.yml
AcmeTasksBundleEntityTask:
type: entity
repositoryClass: AcmeTasksBundleRepositoryTaskRepository
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
AcmeTasksBundleEntityTag:
type: entity
repositoryClass: AcmeTasksBundleRepositoryTagRepository
table: tag
id:
id:
type: integer
generator: { strategy : AUTO }
fields:
name:
type: string
length: 50
manyToMany:
tasks:
targetEntity: Task
mappedBy: tags
数据库架构应该是这样的:
The database schema should like this:
+----------------+ +--------------+
| task | | task_tag | +---------+
+----------------+ +--------------+ | tag |
| id |<--->| task_id | +---------+
| description | | tag_id |<--->| id |
+----------------+ +--------------+ | name |
+---------+
现在我可以生成实体了:
Now I can generate the entities:
app/console generate:doctrine:entities AcmeTasksBundle
这很好,所以可以更新数据库:
This works fine, so the database can be updated:
app/console doctrine:schema:update --force
到目前为止一切正常.这些表在数据库中.现在我想用写操作生成 CRUD:
Everything ok till now. The tables are in the database. Now I want to generate CRUD with write actions:
app/console generate:doctrine:crud --entity=AcmeTasksBundle:Task --with-write --format=yml
在确认几个问题后,它会生成 CRUD 并打印出来:
After confirming few questions it generates the CRUD and prints out:
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
创建了控制器,但没有创建表单.
The controller gets created, but not the form.
在没有写入选项的情况下生成 CRUD 可以正常工作.相同的代码在 Symfony 2.7.7 中完美运行.
Generating the CRUD without write options works fine. The very same code works flawlessly with Symfony 2.7.7.
我检查了文件 form/FormType.php.twig
版本之间的差异,以下是相关部分:
I checked the differences in the file form/FormType.php.twig
between the versions and here are the relevant parts:
Symfony 2.7.7vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/skeleton/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.0vendor/sensio/generator-bundle/Resources/skeleton/form/FormType.php.twig
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代码>.)
As I see the if condition in the for loop is the place where the error occurs. (I assume that the expression fields_mapping[field]['type']
causes the problem since the many to many field (tag
) has no attribute type
.)
我做错了什么?我怎么解决这个问题?非常感谢您的帮助.
What I am doing wrong? How can I solve this problem? Thank you very much for your help.
Symfony 3.0.0 也会出现同样的问题.文件 form/FormType.php.twig
自 2.8 版起已更改.
The same problem occurs with Symfony 3.0.0. The file form/FormType.php.twig
has been changed since version 2.8.
推荐答案
我研究了一下,尝试调试错误.
I was researching a little bit and tried to debug the error.
如上所述,文件 form/FormType.php.twig
自 2.8.0 版本以来已更改.
As I mentioned above, the file form/FormType.php.twig
has been changed since the version 2.8.0.
显然 Symfony 的开发者希望增强表单并自动解析 date
、time
和 datetime
类型.这发生在以下行:
Obviously the Symfony makers wanted to enhance the forms and automatically resolve the types date
, time
and datetime
. This happens in the line:
{%- if fields_mapping[field]['type'] in ['date', 'time', 'datetime'] %}
这应该借助数组fields_mapping
来实现.
This should be achieved with the help of the array fields_mapping
.
通过一些快速而简单的解决方法,我试图找出隐藏在 fields_mapping
中的内容.这是我的模型的结果:
With some quick-and-dirty workarounds I tried to find out what is hidden inside of fields_mapping
. This is the result for my model:
任务
{
id => {
id => 1,
fieldName => id,
type => integer,
columnName => id
},
description => {
fieldName => description,
type => text,
columnName => description
}
}
当遍历Task的字段时,在最后一步遍历字段tags
.if 子句中的表达式如下所示:
When iterating through the fields of Task, in the last step it goes through the field tags
. The expression in the if clause looks like this:
fields_mapping['tags']['type']
我们在前面的例子中看到,Task的fields_mapping
中没有关键的tags
,只有id
和description代码>.由于键
tags
不存在,因此抛出错误.
As we see in the previous example, there is no key tags
in the fields_mapping
for Task, only id
and description
. Since the key tags
doesn't exist, the error is thrown.
我将文件 form/FormType.php.twig
中的相关行更改为如下所示:
I changed the concerned line in the file form/FormType.php.twig
to look like this:
{%- if fields_mapping[field] is defined and fields_mapping[field]['type'] in ['date', 'time', 'datetime'] %}
现在我们可以使用新功能,并通过检查数组中是否存在键来防止错误.
Now we can use the new feature and we prevent an error by checking if the key exists in the array.
我不知道这是一个错误还是在我的特定情况下有什么问题.现在距离 2.8.0 和 3.0.0 版本发布已经一周了,所以可能有成千上万的用户在玩它们.我不敢相信,如果它是一个错误,没有人会注意到这一点.
I don't know if this is a bug or there is something wrong in my particular case. Now it is already one week since the release of the versions 2.8.0 and 3.0.0, so probably many thousands users have been playing around with them. I couldn't believe that, if it is a bug, nobody would have noticed this.
我在 GitHub 上发布了一个问题:
I posted an issue on GitHub:
https://github.com/sensiolabs/SensioGeneratorBundle/issues/443
这是一个错误,已经以同样的方式解决了,正如我在上面所想和写的:
This was a bug, that has been solved in the same way, as I thought and wrote above:
https://github.com/Maff-/SensioGeneratorBundle/commit/205f64e96a94759f795271cb00fc86fb03b1fd4a
https://github.com/Maff-/SensioGeneratorBundle/commit/205f64e96a94759f795271cb00fc86fb03b1fd4a
相关文章