8

我已经完成了很多锂教程(下面的链接以防他们帮助其他人,也表明我已经完成了我的作业:) 我了解创建模型、视图、控制器和使用 MVC 创建的最基本部分基于表单输入的数据库记录。

但是,我是 webapps 和 Lithium 的 MVC 新手,我不确定在更复杂的情况下应该如何编写代码。这是一个一般性问题,但我有两个具体的验证问题:

  • 我应该如何验证从表单提交的日期数据?
  • 我应该如何检查两个用户电子邮件字段是否具有相同的值?

对于这些问题的任何帮助,我将不胜感激,像这样的具体示例也将真正帮助我理解如何在其他情况下进行良好的 MVC 编码!

日期输入 - 验证跨多个表单输入拆分的数据

出于 UI 原因,注册表单要求用户在三个字段中输入他们的出生日期:

<?=$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(/*...*/))); ?>

验证此服务器端的最佳方法是什么?我认为我应该利用自动验证,但我不确定对于一组不属于模型的变量的最佳方法。例如:

  • 我应该对$this->request->datain 进行后处理UsersController吗?例如$this->request->data,在UsersController将其传递给Users::create.
  • 我应该将表单字段拉出$this->request->data并使用对Validator::isDateinside的静态调用UsersController吗?
  • 有没有办法在模型中为不属于模型的表单变量组合编写验证规则?
  • 我应该在那里覆盖Users::create并进行所有额外的验证和后处理吗?

所有这些似乎都可以工作,虽然有些看起来有点难看,我不知道哪些会在未来给我带来重大问题。

[编辑:与此密切相关的是将三个表单字段组合成一个字段以保存在模型中的问题]

电子邮件输入 - 检查两个表单字段是否相同,但只存储一个

对于常识/惯例,注册表单要求用户指定他们的电子邮件地址两次:

<?=$this->form->field('email_address'); ?>
<?=$this->form->field('verify_email_address'); ?>

如何编写一个自动验证规则来检查这两个表单字段是否具有相同的值,但只将 email_address 保存到数据库中?

这感觉它与上述问题几乎相同,因为我能想到的可能答案列表是相同的 - 所以我将其作为一个问题提交,但我非常感谢你对这两个部分的帮助,因为我认为这个解决方案将是微妙的、不同的、同样具有启发性的!

[编辑:与此密切相关的是未将 verify_email_address 存储到我的模型和数据库中的问题]

关于锂的一些背景阅读

我读过其他人,但是这三个教程让我现在与用户在一起并注册表格......

关于密切相关主题的其他一些 StackOverflow 问题(但没有回答,也不是锂特定的)

  • 这个问题的一个答案建议创建一个单独的控制器(和模型和......?) - 我觉得它不是很“锂”,我担心它也可能很脆弱/容易出错
  • 这个精彩的故事让我确信我担心将其放入控制器是正确的,但我不确定什么是好的解决方案
  • 这个视图让我认为我应该以某种方式将其放入模型中,但我不知道在锂中执行此操作的最佳方法(请参阅上面日期条目下的项目符号列表)
  • 这个Scribd 演示文稿问了我希望在最后一页回答的问题……于是它停止了,没有回答!

注意:CakePHP 风格的答案也很好。我不知道,但它很相似,如果需要,我相信我可以从中翻译!

4

1 回答 1

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');
}

将数据设置为实体的一个优点是,如果出现验证错误,它将自动预填充到您的表单中。

于 2012-04-03T23:13:30.407 回答