php – Lithium和验证复杂的表单输入 – 如何?

我已经做了很多Lithium教程(如果他们帮助别人,下面的链接,以及表明我已完成我的作业:)我了解创建模型,视图,控制器和使用MVC创建的最基本部分基于表单输入的DB记录.

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

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

我非常感谢对这些问题的任何帮助,这样的具体例子也将真正帮助我理解如何在其他情况下做好MVC编码!

日期输入 – 验证跨多个表单输入的数据分割

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

<?=$this->form->field('birthday',array('type' => 'select','list' => array(/*...*/))); ?>
<?=$this->form->field('birthmonth','list' => array(/*...*/))); ?>
<?=$this->form->field('birthyear','list' => array(/*...*/))); ?>

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

>我应该在UsersController中对$this-> request->数据进行后期处理吗?例如.在将Users_troller传递给Users :: create之前修改$this-> request->数据.
>我应该从$this-> request->数据中提取表单字段,并在UsersController中使用对Validator :: isDate的静态调用吗?
>有没有办法在模型中为不属于模型的表单变量组合编写验证规则?
>我应该覆盖Users :: create并在那里进行所有额外的验证和后处理吗?

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

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

电子邮件条目 – 检查两个表单字段是相同的,但只存储一个

对于常识/常规做法,注册表单要求用户指定两次电子邮件地址:

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

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

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

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

一些关于锂的背景阅读

我已经读过其他人了,但这三个教程让我到了用户所在的位置并立即注册表单…

> Blog tutorial
> Extended blog tutorial
> MySQL blog tutorial

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

> this question一个答案建议创建一个单独的控制器(和模型……?) – 它对我来说感觉不太“锂”,我担心它可能很脆弱/很容易出错
> This wonderful story让我确信我担心把它放在控制器中是对的,但我不确定什么是好的解决方
> This one on views让我觉得我应该以某种方式将它放在模型中,但我不知道在Lithium中执行此操作的最佳方法(请参阅上面日期条目下的项目符号列表)
>并且this Scribd演示文稿询问了我希望在最后一页回答的问题……于是它停止了而没有回答它!

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

我建议在模型而不是控制器中执行此操作 – 无论您从何处执行保存,都会发生这种情况.

对于日期字段问题,在模型中,覆盖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","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');
}

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

相关文章

统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
前言 之前做了微信登录,所以总结一下微信授权登录并获取用户...
FastAdmin是我第一个接触的后台管理系统框架。FastAdmin是一...
之前公司需要一个内部的通讯软件,就叫我做一个。通讯软件嘛...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...