首先,我要说,我发现sfFormPropel表单的接口不一致。
有bind()
,它不返回任何内容,但触发验证,save()
返回保存的对象,bindAndSave()
返回布尔值,实际上是isValid()
的返回值。现在,我有一个有效的应用程序,但我觉得代码不对,我对symfony
很新,所以也许我错过了什么。
我需要创建的对象需要一些外部属性,这些外部属性不在表单中显示,在模型外部,并由应用程序处理(例如,用户的userId,创建实体,外部生成的guid等)。
现在流程如下:
显而易见的答案是将特定于应用程序的值添加到从请求中检索的值,但如果表单无效,则绑定特定于应用程序的值没有意义,因为它们可能很昂贵操作,可能会创建数据库记录等。此外,不应该使用post请求传递这些值,它们应该仅来自应用程序。
现在,虽然我必须让模型做这些事情,但由于数据在模型外部,因此操作仍然需要将其传递给模型。问题是,如果我在$form->getObject()
之后拨打bind()
,它仍然有旧数据,而不是提交的数据。
实现这种后处理的正确方法是什么?
第二个赏金开始奖励其他有价值的答案
答案 0 :(得分:2)
正确的方法是在传递给表单构造函数的对象上设置默认值。例如,如果要在要创建的对象上设置登录用户ID:
$article = new Article();
$article->setUserId($this->getUser()->getId());
$form = new ArticleForm($article);
if ($request->isMethod('post')) {
$form->bind($request->getParameter('article'));
if ($form->isValid()) {
$form->save();
}
}
同样对于现有对象,您可以在将记录传递给表单构造函数之前加载记录并更改任何属性。
编辑:
如果要在验证后修改对象,可以使用$ form-> updateObject(),就像Grad在他的回复中建议的那样。如果生成的值取决于提交的值,则可以覆盖sfFormObject :: processValues():
class UserForm {
public function processValues($values) {
$values['hash'] = sha1($values['id'] . $values['username']);
return parent::processValues($values);
}
}
如果您需要操作中的某些内容,您可以随时将其作为选项传递给表单:
$form = new UserForm($user, array('foo' => $bar));
这样,您可以在表单代码中的任何位置使用$ this-> getOption('foo'),例如。 in processValues()。
答案 1 :(得分:1)
这取决于谁具有关于额外属性的“知识”。如果它们确实是特定于请求,因此需要在控制器中进行处理,我会进行绑定,测试是否有效,然后更新绑定对象。要使用绑定(和验证)字段获取更新的对象,请使用updateObject
函数。
$form->bind(..)
if ($form->isValid()) {
$obj = $form->updateObject(); // Updates the values of the object with the cleaned up values. (returns object)
$obj->foo = 'bar';
$obj->save();
}
但由于这通常也是特定于表单的行为,因此我通常会覆盖Form类。通过覆盖doUpdateValues()
功能,您可以轻松访问提交的数据,并附加您自己的数据。当然,您也可以在链中走得更高,并覆盖save()
函数。
要为此表单设置自定义数据,您还可以“发布”公共方法,然后由控制器使用。