在提交新项目时,Symfony会处理POST数据,但新持久化的项目没有在相应的隐藏字段值属性中填充其ID,而是缺少value属性。
我已实施了一些添加/修改/删除功能,让用户使用CollectionType管理“城市”实体池。
添加新城市时:
除了事实上任何新提交的城市的隐藏字段缺少“值”属性之外,所有工作都有效。
我读过像 在刷新后立即访问对象getter返回相应的最新属性。新插入的记录ID将填充...
所以我希望Doctrine在刷新时更新新的持久化城市对象,但看起来没有任何事情发生。 表单似乎没有意识到新的插入。这是因为在处理请求后Forms数据不可变吗? 注意:至少,在重新加载页面时(在没有发布数据两次的情况下到达相同的URL),隐藏字段最终会使其属性值打印出相应的实体ID。
有人可以帮我看一下这里需要做什么,以便在提交后立即正确呈现隐藏字段(包含预期实体ID的«value»属性)?
控制器......
<?php
// ...
/**
* @Route("/cities", name="admin_config_cities")
*/
public function configureCitiesAction(Request $request)
{
# Retrieving existing cities
$em = $this->getDoctrine()->getManager();
$cities = $em->getRepository('AppBundle:City')->findAll();
# Associate cities ids with corresponding objects
$sorted = [];
array_walk($cities, function ($value, $key) use (&$sorted) {
$sorted[ $value->getId() ] = $value;
});
# Initialize form
$citiesForm = $this->createForm(
CollectionType::class,
$cities,
[
'entry_type' => CityType::class,
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
# I thought "mapped" option would do the trick.
# worse, seems to do nothing
'mapped' => true,
'label' => false,
'entry_options' => [
'label' => false,
'by_reference'=>true
]
]
);
if ($request->isMethod('POST')) {
$citiesForm->handleRequest($request);
if ($citiesForm->isValid()){
# Persist any submitted datas
foreach( $citiesForm->getData() as $city ){
$id = $city->getId();
if ($id && array_key_exists($id,$sorted)) {
unset($sorted[$id]);
}
$em->persist($city);
}
# Remove discared cities
foreach( $sorted as $removed ){
$em->remove($removed);
}
$em->flush();
}
}
# TODO: find the way to make newly added cities to be rendered
# along with their ID available inside an hidden field's attribute
# right after submission (without the need of a refresh)
return $this->render('AppBundle:admin:config/cities.html.twig', [
'form' => $citiesForm->createView()
]);
}
CityType包含隐藏字段
//…
$builder->add( 'id', HiddenType::class, [ 'required'=>false ])
//…
相关模板
{# … #}
{{ form_start(form) }}
<div data-prototype="{{ form_widget(collection.vars.prototype)|e }}">
{% for item in collection %}
{{ form_widget(item) }}
{% endfor %}
<p>
<a class="btn btn-default btn-sm" title="{{ 'button-add-title'|trans }}">{{ 'button-add-caption'|trans }}</a>
</p>
</div>
<p class="text-right">
<button type="submit">Submit</button>
</p>
{{ form_end(form) }}
跳得很清楚,谢谢。
by_reference
在集合entry_options
内设置为true
我做过的测试说:它只对那里有影响。 True可以更新DB中的相应(现有)记录。另一方面,false会阻止映射,从而导致数据库中出现重复的条目
在集合本身上设置by_reference
似乎根本就什么都不做
也就是说,新记录实际上是持久存在的,但是这个新创建的元素的修改会导致随机行为(由于allow_delete而被删除,发出了重复的条目)。仍然开发工具DOM树不显示隐藏字段的value
属性,导航器源快捷方式 Ctrl + u 也不显示。一旦发出新的GET请求,就会出现值属性神奇。
这里有一些我不明白的事情:/
。
最后,我发现确保使用正确填充的隐藏字段来呈现表单的唯一方法是在$this->redirect($this->generateUrl($_route));
之后命令flush()
。