Symfony:添加记录后更改响应

时间:2012-01-07 13:52:01

标签: php jquery ajax symfony1 propel

我通过ajax打开一个表单(使用jquery),我想保存它而不重新加载整个页面。我必须更改代码,获取文本响应(例如“ok!”)而不是重定向到编辑页面?

这是我的js:

$("#newcatlink").click(function() {
    $.ajax({
    'url': "category/new",
    'success': function(data, textStatus, jqXHR) {
            $("#mdialog").html(data);
            $("#_form_jqhide").hide();
            $("#mdialog").dialog({
                modal: true,
                width: 500,
                resizable: false,
                buttons: {
                    Save: function() {
                        $.ajax({
                            'type': 'POST', 
                            'url': 'category/create', 
                            'data': $("#categoryform").serialize(),
                            'success': function(data, textStatus, jqXHR) {
                                alert(data);
                            }
                        });
                    },
                    Cancel: function() {
                        $(this).dialog("close");
                    }
                }
            });
        }
    });
});

我在actions.class.php中更改了processForm操作,如下所示:

...
if ($form->isValid())
{
  $Category = $form->save();

        if($request->isXmlHttpRequest()) {
            return $this->renderText("ok!");
        } else {
            $this->redirect('category/edit?id='.$Category->getId());
        }
}

但它没有改变任何东西。怎么做?

编辑8/1/12:

我根据blowski和sakfa的答案对我的代码进行了更改,但我得到另一个问题:如何捕获表单错误?我将processForm else添加到if并且它按预期工作但我无法获得错误消息/代码/无论如何,只有错误存在的事实。

以下是代码:http://pastebin.com/ppbPM88G 这是服务器答案后发送表单,其中一个必填字段为空:

  

{ “haserrors”:真, “错误”:[]}

2 个答案:

答案 0 :(得分:2)

基于此处的对话:

您已将return $this->renderText("ok!")方法中的processForm置于不执行状态(如executeCreate)。将返回行和条件检查移动到executeXXX方法。

编辑2012-01-08

我删除了旧的代码段,因为它们现在没有任何用处,因为您编辑了原始代码,有效地将我的更改纳入其中。

关于你的新问题:

基本上symfony1 api在处理表单时很糟糕,这就是你遇到这么多问题的原因。

首先,你需要知道这个api不是为了处理AJAX表单提交而设计的 - 这是因为sfForm可以自我验证,可以在内部存储它的错误并且可以将它们呈现为HTML - 但是没有例程(据我所知)以某种可序列化的格式返回错误(比如一个fieldname => errorMessage对的数组,json_encodes很好)。

从您的代码开始,我将在您的位置做的是:

首先:假设您执行POST请求

,仅为ajax提交处理创建单独的操作
public function exucuteAjaxFormSubmission(sfWebRequest $request)
{
    //this action handles ONLY ajax so we can safely set appropriate headers
    $this->getResponse()->setContentType('text/json');

    $form = new form();
    $form->bind($request->getPostParameters());

    if ($form->isValid()) {
        //do your logic for positive form submission, i.e. create or update record in db
        return json_encode('ok'); //notify client that everything went ok
    } else {
        return $this->doSomeMagicToGetFormErrorsAsAnJsonEncodedArray();
    }
}

现在到doSomeMagicToGetFormErrorsAsAnJsonEncodedArray部分:您希望以json格式获取表单错误。为此,我们将为您的表单类添加一个简单的方法(因为这是验证逻辑的'接口')。

一些理论:内部sfForm在一个名为sfValidatorErrorSchema的结构中存储验证错误。 sfValidatorErrorSchema将错误存储在两个列表中 - namedErrorsglobalErrors。命名错误是为“字段验证器”抛出的错误(即name字段上需要的字符串验证器。全局错误是整个表单抛出的错误(即全局postValidators)。每个错误都是由违规验证器抛出的sfValidatorError对象。

警告:实际上这个结构是递归的,但是只有在使用嵌入式表单时才会看到它在这种情况下,必须更改以下函数以包含sfValidatorErrorSchema可以包含另一个sfValidatorErrorSchema的情况,而不是sfValidatorError ..我希望你不要使用嵌入式表格,因为这在symfony中比简单的API更糟糕。

但是,如果您只想要代码,那么请将这些方法粘贴到您的表单类中:

class myForm extends sfForm { 
    (...)

    /** a helper method to convert error schema to an array */
    public function getSerializableErrors()
    {
        $result = array();
        foreach ($this->getErrorSchema()->getNamedErrors() as $fieldName => $error) {
            $result[$fieldName] = $error->getMessage();
        }
        foreach ($this->getErrorSchema()->getGlobalErrors() as $error) {
            $result['_globals'][] = $error->getMessage();
        }

        return $result;
    }

    /** screw array, just give me ready to send json! */
    public function getJsonEncodedErrors()
    {
        return json_encode($this->getSerializableErrors());
    }
}

现在只需将doSomeMagicToGetFormErrorsAsAnJsonEncodedArray更改为getJsonEncodedErros即可完成基本的ajax表单发布验证 - 您现在应该有足够的知识来正确实现逻辑。我已经在当前的symfony 1.4版本上测试了这个,所以如果出现任何问题,可能是旧版本的sf问题(你没告诉我你使用的是哪个版本)

答案 1 :(得分:1)

根据我们的谈话,我可以看到发生了什么。如果我理解了你的评论,它不会重定向整个页面,它只是在对话框中重新渲染原始表单?

用户提交表单后,如果有效,则重定向。但是,由于您绕过重定向,它会转到代码的$this->setTemplate('new')位,因此会再次显示new表单,并填充刚刚完成的表单中的数据。

要解决此问题,请在创建操作中使用以下内容:

if($request->isXmlHttpRequest()) {
  $this->renderText(json_encode(array('valid' => $form->isValid())));
} else {
  $this->setTemplate('new');
}

您还需要更改Ajax请求以指定它期望JSON响应。然后,如果表单有效,请关闭对话框(或保存后要执行的任何操作)。