我正在尝试通过 REST API 传递表单数据。 API 是在 Symfony (2.7) 中构建的,实际的数据输入表单位于外部非 symfony 站点上。表单提交得很好,直到我尝试传递一对“集合”。
我一直在关注this tutorial因此我的 Type 类中有以下内容:
$form->add('event', 'collection', array(
'type' => new AvRequestEventType(),
'allow_add' => true,
'by_reference' => false,
));
$form->add('equipment', 'collection', array(
'type' => new AvRequestEquipmentQuantityType(),
'allow_add' => true,
'by_reference' => false,
));
我的数据输入表单如下所示(我将仅显示“事件”集合,因为“设备”集合代码本质上是相同的):
var eventsPrototype = '<div id="event___name__" class="row"><div class="small-8 columns"><label for="event___name___location">Location<input type="text" id="event___name___location" name="[event][__name__][location]" maxlength="100" /></label></div><div class="small-4 columns"><label for="event___name___time">Time<input type="time" id="event___name___time" name="[event][__name__][time]" /></label></div></div>';
var $eventsHolder;
var $addEventLink = $('<a href="#" class="add_event_link">Add Event</a>');
var $newLinkLi = $('<li></li>').append($addEventLink);
$eventsHolder = $('ul.events');
$eventsHolder.append($newLinkLi);
/*
count the current form inputs we have (e.g. 2), use that as the new
index when inserting a new item (e.g. 2)
*/
$eventsHolder.data('index', $eventsHolder.find(':input').length);
//add a new event form on page load
addEventForm($eventsHolder, $newLinkLi);
$addEventLink.on('click', function(event){
event.preventDefault();
//add a new event form
addEventForm($eventsHolder, $newLinkLi);
});
function addEventForm($eventsHolder, $newLinkLi) {
// get the new index
var index = $eventsHolder.data('index');
// Replace '__name__' in the prototype's HTML to
// instead be a number based on how many items we have
var newForm = eventsPrototype.replace(/__name__/g, index);
// increase the index with one for the next item
$eventsHolder.data('index', index + 1);
// Display the form in the page in an li, before the "Add a tag" link li
var $newFormLi = $('<li></li>').append(newForm);
$newLinkLi.before($newFormLi);
}
当提交表单时,这是 AJAX 调用:
ajaxObject = {
url: $("#postform").attr("action"),
type: 'POST',
dataType: 'json',
xhrFields: {
withCredentials: true
},
crossDomain: true,
data: $("#postform").serialize()
};
$.ajax(ajaxObject)
.success(function(data, status, xhr) {
...
})
.fail(function(data, status, xhr) {
...
})
.always(function(data, status, xhr) {
...
});
假设我创建了两个事件。请注意,事件实体有两个字段,位置和时间(采用“时间”格式)。这是作为这些事件的数据发送的内容的示例:
[event][0][location]:Event A
[event][0][time]:22:22
[event][1][location]:Event B
[event][1][time]:22:11
在我的 Symfony REST Controller 内,我创建一个新的未命名表单来处理提交:
$form = $this->get('form.factory')->createNamed('', new AvRequestType(), $entity);
$form->handleRequest($request);
...validation and whatnot
更新:
尝试添加集合数组时,生产日志会产生以下错误:
"The Response content must be a string or object implementing __toString(), "array" given."
我知道这意味着我必须以某种方式将集合数组转换为字符串才能被 Symfony 接受。但如何呢?在将整个表单传递给 Symfony 之前,我已经通过 Javascript 序列化了整个表单。我想如果我在集合中有固定数量的项目,我可以 JSON.stringify() 每个表单字段,但这似乎不是一个非常优雅的解决方案。
最佳答案
解决这个问题的方法是表单需要有一个名称。
所以而不是...
$form = $this->get('form.factory')->createNamed('', new AvRequestType(), $entity);
...必须给出名称...
$form = $this->get('form.factory')->createNamed('myrequestform', new AvRequestType(), $entity);
这允许 Symfony(无论如何我假设)将所有字段识别为属于同一请求。因此,请求不要像这样:
eventDate:2016-02-01
pickupDate:2016-02-29 09:45:00
returnDate:2016-02-17 06:30:00
attendees:32
specialInstruction: special
[event][0][location]:LA
[event][0][time]:00:00
[event][1][location]:LB
[event][1][time]:11:11
现在看起来像这样:
avrequest[eventDate]:2016-02-01
avrequest[pickupDate]:2016-02-29 09:45:00
avrequest[returnDate]:2016-02-17 06:30:00
avrequest[attendees]:32
avrequest[specialInstruction]: sepcial
avrequest[event][0][location]:LA
avrequest[event][0][time]:00:00
avrequest[event][1][location]:LB
avrequest[event][1][time]:11:11
当您考虑如何在 Symfony 中提交表单时,这是有道理的;每个表单元素的名称属性的布局完全相同。
如果有人想添加比这更优雅的解释,请随意。
关于jquery - Symfony2 : Add Collection via AJAX Outside of Symfony,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35212373/