我做了很多Lithium教程(如果他们帮助别人,下面的链接,以及表明我完成了我的作业:)我了解创建模型,视图,控制器和使用的最基本部分MVC根据表单输入创建数据库记录。
但是,我是MVC for webapps和Lithium的新手,我不确定如何在更复杂的情况下编写代码。这是一个普遍的问题,但我有两个具体的验证问题:
我非常感谢对这些问题的任何帮助,这样的具体例子也将真正帮助我理解如何在其他情况下做好MVC编码!
出于用户界面原因,注册表单会要求用户在三个字段中输入他们的DOB:
<?=$this->form->field('birthday', array('type' => 'select', 'list' => array(/*...*/))); ?>
<?=$this->form->field('birthmonth', array('type' => 'select', 'list' => array(/*...*/))); ?>
<?=$this->form->field('birthyear', array('type' => 'select', 'list' => array(/*...*/))); ?>
验证此服务器端的最佳方法是什么?我想我应该利用自动验证,但我不确定对于一组不属于模型的变量的最佳方法。 E.g:
$this->request->data
中对UsersController
进行后期处理吗?例如。在将$this->request->data
传递给UsersController
之前修改Users::create
内的$this->request->data
。Validator::isDate
中提取表单字段并使用UsersController
内的Users::create
静态调用吗?<?=$this->form->field('email_address'); ?>
<?=$this->form->field('verify_email_address'); ?>
并在那里进行所有额外的验证和后期处理吗?所有这些似乎都可以起作用,虽然有些看起来有点难看,但我不知道哪些可能会给我带来重大问题。
[编辑:与此密切相关的是将三个表格字段合并为一个字段以保存在模型中的问题]
对于常识/常规做法,注册表单会要求用户指定两次电子邮件地址:
{{1}}
如何编写一个自动验证规则来检查这两个表单字段是否具有相同的值,但只将email_address保存到数据库中?
这感觉就像上面几乎一样的问题,因为我能想到的可能答案清单是一样的 - 所以我提交这个作为一个问题,但我真的很感谢你的帮助这两个部分,因为我认为这个部分的解决方案将是微妙的,不同的,同样具有启发性!
[编辑:与此密切相关的是不将verify_email_address存储到我的模型和数据库中的问题]
我已经读过其他人了,但这三个教程让我了解了我与用户的关系并立即注册表单...
关于密切相关主题的其他一些StackOverflow问题(但没有回答它,也没有回答特定于锂的问题)
注意:CakePHP风格的答案也很好。我不知道,但它很相似,如果我需要,我相信我可以从中翻译出来!
答案 0 :(得分:4)
我建议在Model
而不是Controller
中执行此操作 - 无论您从哪里进行保存,都会发生这种情况。
对于日期字段问题,在模型中,覆盖save()
方法并处理将数据中的多个字段转换为一个日期字段,然后再调用parent::save
进行实际保存。任何高级操作都可能发生在那里。
使用隐藏表单字段获取错误消息以显示声音的评论中描述的技术非常好。
为了比较两个电子邮件字段是否相等,我建议您定义一个自定义验证器。您可以使用Validator::add在引导程序中执行此操作。
use lithium\util\Validator;
use InvalidArgumentException;
Validator::add('match', function($value, $format = null, array $options = array()) {
$options += array(
'against' => '',
'values' => array()
);
extract($options);
if (array_key_exists($against, $values)) {
return $values[$against] == $value;
}
return false;
});
然后在你的模型中:
public $validates = array(
"email" => array(
"match",
"message" => "Please re-type your email address.",
"against" => "email2"
)
);
编辑:根据评论,这是在控制器中执行自定义规则验证的方法:
public function save() {
$entity = MyModel::create($this->request->data);
$rules = array(
"email" => array(
"match",
"message" => "Please re-type your email address.",
"against" => "email2"
)
);
if (!$entity->validates($rules)) {
return compact('entity');
}
// if your model defines a `$_schema` and sets `$_meta = array('locked' => true)`
// then any fields not in the schema will not be saved to the db
// here's another way using the `'whitelist'` param
$blacklist = array('email2', 'some', 'other', 'fields');
$whitelist = array_keys($entity->data());
$whitelist = array_diff($whitelist, $blacklist);
if ($entity->save(null, compact('whitelist'))) {
$this->redirect(
array("Controller::view", "args" => array($entity->_id)),
array('exit' => true)
);
}
return compact('entity');
}
将数据设置为实体的一个优点是,如果出现验证错误,它将自动预填到表单中。