Php 在symfony2中提交Ajax表单,为没有javascript的用户提供优雅的降级

Php 在symfony2中提交Ajax表单,为没有javascript的用户提供优雅的降级,php,ajax,forms,symfony,Php,Ajax,Forms,Symfony,我正在构建一个包含表单的web应用程序。正在使用的框架是symfony2。我希望所有的东西都能为没有javascript的用户工作,然后逐步增强启用javascript的用户的体验。我计划使用JQuery作为我的javascript库 如果用户没有javascript,并且请求不是ajax请求,我希望表单能够使用FlashMessage组件提交和显示消息 对于支持javascript的用户,如果提交成功,我想将消息返回给他们。javascript应该立即在div中显示该消息 同时,我需要处理错误

我正在构建一个包含表单的web应用程序。正在使用的框架是symfony2。我希望所有的东西都能为没有javascript的用户工作,然后逐步增强启用javascript的用户的体验。我计划使用JQuery作为我的javascript库

如果用户没有javascript,并且请求不是ajax请求,我希望表单能够使用FlashMessage组件提交和显示消息

对于支持javascript的用户,如果提交成功,我想将消息返回给他们。javascript应该立即在div中显示该消息

同时,我需要处理错误消息。对于没有javascript的用户,整个表单将重新提交,并显示错误消息

对于使用javascript的用户,ajax响应应该是一个包含输入组件id和错误消息的数组。Javascript应该在不刷新的情况下将它们插入表单中

查看symfony2书籍,我可以看到以下提交内容,然后我对其进行了修改,以检查请求是否是ajax请求:

public function newAction(Request $request)
{
    // just setup a fresh $task object (remove the dummy data)
    $task = new Task();

    $form = $this->createFormBuilder($task)
        ->add('task', 'text')
        ->add('dueDate', 'date')
        ->getForm();

    if ($request->getMethod() == 'POST') {
        $form->bindRequest($request);

        if ($form->isValid()) {
            // perform some action, such as saving the task to the database
            if ($this->request->isXmlHttpRequest(){
                   //return data ajax requires.
            } 
            return $this->redirect($this->generateUrl('task_success'));
        }
    }

    // ...
}
我发现这种方法的问题是它不是很优雅。我需要在每张表格上加上额外的支票。此外,如果请求是通过Zend_AMF传入的,那么这种方法将不起作用


有没有更好的方法

只要您能概括出非ajax表单和ajax表单所需的响应类型,您就可以将ajax/非ajax的决策降级到另一种方法,然后只需:

return handleResponseType(whateverInfoIsNeededToHandleIt)

然后,您可以完全控制传递给决策函数的内容。

另一个选项是让控制器返回响应以外的内容,并使用
内核。查看
事件将其转换为您想要的内容。这会更好,因为逻辑封装在侦听器中。你只需要决定你想要你的控制器返回什么

if ($form->isValid()) {
    return new Something($redirectUrl, $ajaxData);
}
在你的听众中:

public function onKernelView($event)
{
    $request = $event->getRequest();
    $result = $event->getControllerResult();

    if ($result instanceof Something) {
        if ($request->isXmlHttpRequest()) {
            $event->setResponse(new Response(json_encode($result->getAjaxData())));
        } else {
            $event->setResponse(new RedirectResponse($result->getRedirectUrl()));
        }
    }
}

您可以像往常一样返回响应,并决定是否要进行部分渲染或通过扩展不同的细枝布局来渲染整个页面

在控制器中:

if ($form->isValid()) {
    // perform some action, such as saving the task to the database
    $this->get('session')->setFlash('notice', 'Success!');
    return $this->render('success.html.twig');
} else {
    $this->get('session')->setFlash('notice', 'Please correct the errors below');
}
在你看来:

{# new.html.twig #}
{% extends app.request.isXmlHttpRequest ? 'ajax.html.twig' : 'layout.html.twig' %}
{% block content %}
    {% if app.session.hasFlash('notice') %}
        <div class="flash-notice">{{ app.session.flash('notice') }}</div>
    {% endif %}
    <form ...>
        {{ form_widget('form') }}
        <input type="submit" />
    </form>
{% endblock %}


{# success.html.twig #}
{% extends app.request.isXmlHttpRequest ? 'ajax.html.twig' : 'layout.html.twig' %}
{% block content %}
    {% if app.session.hasFlash('notice') %}
        <div class="flash-notice">{{ app.session.flash('notice') }}</div>
    {% endif %}
{% endblock %}


{# ajax.html.twig #}
{% block content %}{% endblock %}


{# layout.html.twig #}
<html>
<body> normal page content
    <div id='content'>
    {% block content %}{% endblock %}
    </div>
</body>
</html>
$.ajax({
  type: "POST",
  url: "tasks/new",
  data: {task: foo, dueDate: bar},
}).done(function( msg ) {
  $('#content').html(msg);
});