自从Symfony的最后一个LTS版本在几天前(2015年11月30日)发布以来,我开始玩它。不幸的是,我无法使用在Symfony 2.7.7中运行良好的相同代码的写操作生成CRUD。
首先,我使用Linux Mint 17.2下的bash
创建一个新的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
并为我的模型放置两个文件。这些是:
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']
导致问题,因为多对多字段(tag
)没有属性type
。)
我做错了什么?我怎么解决这个问题?非常感谢你的帮助。
编辑:
Symfony 3.0.0也出现同样的问题。自版本2.8以来,文件form/FormType.php.twig
已更改。
答案 0 :(得分:17)
在生成器包中datetime fix之后看起来像回归。
快速解决方案是在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'] %}
除非该错误根据相同的假设掩盖更多隐藏错误。
答案 1 :(得分:17)
我正在研究一下,并尝试调试错误。
正如我上面提到的,自版本2.8.0以来文件form/FormType.php.twig
已经更改。
显然,Symfony制造商希望增强表单并自动解决类型date
,time
和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
for task中没有关键fields_mapping
,只有id
和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
答案 2 :(得分:3)
即使在更新固定包之后问题仍然存在,有时解决问题的最简单方法是删除vendor
目录,并更新作曲家。