【问题标题】:Symfony: change response after adding recordSymfony:添加记录后更改响应
【发布时间】:2012-02-04 21:50:29
【问题描述】:

我通过 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":true,"errors":[]}

【问题讨论】:

  • 它还在重定向到分类/编辑页面?在返回 $this->renderText('ok!') 之前添加一个 die('here') 语句以检查它是否进入该分支。
  • with die,它按预期显示“here”。没有死,重定向到编辑页面。
  • 我想不出它为什么继续运行重定向。动作类中的其他任何地方肯定没有重定向?通常为此我使用if(!$request->isXmlHttpRequest()) { $this->redirect() },并将文本渲染放在公共方法中。
  • pastebin.com/S4MnPRx7 这就是完整的 processForm 方法。没有其他任何改变。
  • 好的,尝试在重定向前添加die('here')。如果这不会杀死脚本,那么重定向肯定来自其他地方。

标签: php jquery ajax symfony1 propel


【解决方案1】:

根据这里的对话:

您已将return $this->renderText("ok!") 放入processForm 方法中,但未执行(如executeCreate)。将返回行和条件检查移到executeXXX方法。

编辑 2012-01-08

我已经删除了旧的 sn-ps 代码,因为它们现在没有任何用处,因为您编辑了原始代码,有效地合并了我的更改。

关于你的新问题:

基本上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 将错误存储在两个列表中 - namedErrors 和 globalErrors。命名错误是为“字段验证器”抛出的错误(即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 版本的问题(你没有告诉我你使用的是哪个版本)

【讨论】:

  • 感谢您的回答。我在我的问题中添加了另一个相关问题
  • 阅读编辑后的版本,它包含了您新问题的答案
  • 非常感谢您!一切正常!非常感谢!
【解决方案2】:

根据我们的谈话,我可以看到正在发生的事情。如果我理解你的 cmets,它不是重定向整个页面,它只是在对话框内重新呈现原始表单?

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

要绕过它,请在创建操作中使用类似的内容:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多