简体   繁体   English

锂和验证复杂表格的输入-怎么样?

[英]Lithium and validating complex form inputs - how?

I've done quite a few Lithium tutorials (links below in case they help someone else, and also to show I've done my homework:) and I understand the most basic parts of creating models, views, controllers and using MVC to create a DB record based on form input. 我已经完成了很多Lithium教程(下面的链接,以防其他人帮忙,也表明我已经完成了功课:),并且我了解创建模型,视图,控制器以及使用MVC进行创建的最基本部分基于表单输入的数据库记录。

However, I'm new to MVC for webapps and Lithium, and I'm not sure how I should write my code in more complicated situations. 但是,我不熟悉MVC for webapps和Lithium,因此我不确定在更复杂的情况下应该如何编写代码。 This is a general question, but two specific validation questions that I have are: 这是一个一般性问题,但是我有两个具体的验证问题:

  • How should I validate date data submitted from the form? 如何验证从表单提交的日期数据?
  • How should I check that the two user email fields have the same value? 如何检查两个用户电子邮件字段的值相同?

I would be very grateful for any help with these questions, and concrete examples like this will also really help me understand how to do good MVC coding in other situations as well! 我将非常感谢您对这些问题的帮助,像这样的具体示例也将确实帮助我理解在其他情况下如何进行良好的MVC编码!

Date entry - validating data split across multiple form inputs 日期输入-验证跨多个表单输入拆分的数据

For UI reasons, the sign up form asks users to enter their DOB in three fields: 由于用户界面的原因,注册表单要求用户在三个字段中输入其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(/*...*/))); ?>

What is the best way to validate this server-side? 验证此服务器端的最佳方法是什么? I think I should take advantage of the automagic validation, but I'm not sure of the best way do that for a set of variables that aren't really part of the Model. 我认为我应该利用自动验证的优势,但是我不确定对于不是模型真正一部分的一组变量的最佳方法。 Eg: 例如:

  • Should I post-process the $this->request->data in UsersController ? 我应该在UsersController中对$this->request->data进行后处理吗? Eg modify $this->request->data inside UsersController before passing it to Users::create . 例如:调整$this->request->data里面UsersController它传递给前Users::create
  • Should I pull the form fields out of $this->request->data and use a static call to Validator::isDate inside UsersController ? 我应该从$this->request->data拉出表单字段,并在UsersController使用对Validator::isDate的静态调用吗?
  • Is there a way to write a validation rule in the model for combinations of form variables that aren't part of the model? 是否可以在模型中为不属于模型的形式变量的组合编写验证规则?
  • should I override Users::create and do all the extra validation and post-processing there? 我应该覆盖Users::create并在那里进行所有额外的验证和后处理吗?

All of these seem like they could work, although some seem a little bit ugly and I don't know which ones could cause major problems for me in the future. 所有这些似乎都可以工作,尽管有些看起来有些丑陋,我不知道将来哪些会给我造成重大问题。

[EDIT: Closely related to this is the problem of combining the three form fields into a single field to be saved in the model] [编辑:与此密切相关的是将三个表单字段组合为一个要保存在模型中的字段的问题]

Email entry - checking two form fields are identical, but only storing one 电子邮件输入-检查两个表单字段是否相同,但仅存储一个

For common sense/common practice, the sign up form asks users to specify their email address twice: 对于常识/常识,注册表单要求用户两次指定其电子邮件地址:

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

How can I write an automagic validation rule that checks these two form fields have the same value, but only saves email_address to the database? 如何编写自动验证规则来检查这两个表单字段的值相同,但仅将email_address保存到数据库?

This feels like it's pretty much the same question as the above one because the list of possible answers that I can think of is the same - so I'm submitting this as one question, but I'd really appreciate your help with both parts, as I think the solution to this one is going to be subtle and different and equally enlightening! 感觉与上面的问题几乎是相同的问题,因为我可以想到的可能答案的列表是相同的-因此,我将其作为一个问题提交,但非常感谢您在这两部分中的帮助,我认为解决这一问题的方法将是微妙的,不同的,并且同样具有启发性!

[EDIT: Closely related to this is the problem of not storing verify_email_address into my model and DB] [编辑:与此密切相关的是不将verify_email_address存储到我的模型和数据库中的问题]

Some background reading on Lithium 关于锂的一些背景阅读

I've read others, but these three tutorials got me to where I am with users and sign up forms now... 我读过其他人,但是这三个教程使我了解了与用户的关系,现在就注册表格...

Some other StackOverflow questions on closely related topics (but not answering it and also not Lithium-specific) 有关紧密相关主题的其他一些StackOverflow问题(但不回答,也不是锂专用的)

  • One answer to this question suggests creating a separate controller (and model and...?) - it doesn't feel very "Lithium" to me, and I'm worried it could be fragile/easily buggy as well 这个问题的一个答案建议创建一个单独的控制器(以及模型和...?)-对我来说感觉不太“锂”,我担心它也可能很脆弱/容易出故障。
  • This wonderful story convinced me I was right to be worried about putting it in the controller, but I'm not sure what a good solution would be 这个奇妙的故事使我确信,我担心将其放入控制器中是正确的,但是我不确定会有什么好的解决方案
  • This one on views makes me think I should put it in the model somehow, but I don't know the best way to do this in Lithium (see my bulleted list under Date Entry above) 这一观点使我认为我应该以某种方式将其放入模型中,但是我不知道在锂离子电池中执行此操作的最佳方法(请参见上方“日期输入”下的项目符号列表)
  • And this Scribd presentation asked the question I'm hoping to answer on the last page... whereupon it stopped without answering it! 然后这个 Scribd演示文稿问了我希望在最后一页上回答的问题...于是它停止了而没有回答!

NB: CakePHP-style answers are fine too. 注意:CakePHP风格的答案也很好。 I don't know it, but it's similar and I'm sure I can translate from it if I need to! 我不知道,但是很相似,我确信可以根据需要从中进行翻译!

I'd recommend doing this in the Model rather than the Controller - that way it happens no matter where you do the save from. 我建议您在Model而不是Controller执行此操作,这样无论您从何处进行保存,都会发生这种情况。

For the date field issue, in your model, override the save() method and handle converting the multiple fields in the data to one date field before calling parent::save to do the actual saving. 对于日期字段问题,在您的模型中,重写save()方法,并在调用parent::save进行实际保存之前,将数据中的多个字段转换为一个日期字段。 Any advanced manipulation can happen there. 任何高级操作都可以在那里发生。

The technique described in your comment of using a hidden form field to get error messages to display sounds pretty good. 您的注释中描述的使用隐藏的表单字段获取错误消息以显示声音的技术非常好。

For comparing that two email fields are equal, I'd recommend defining a custom validator. 为了比较两个电子邮件字段是否相等,我建议定义一个自定义验证器。 You can do this in your bootstrap using Validator::add . 您可以使用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;
});

Then in your model: 然后在您的模型中:

public $validates = array(
    "email" => array(
        "match",
        "message" => "Please re-type your email address.",
        "against" => "email2"
    )
);

Edit : Per the comments, here's a way to do custom rule validation in a controller: 编辑 :根据评论,这是在控制器中执行自定义规则验证的方法:

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

An advantage of setting the data to the entity is that it will be automatically prefilled in your form if there's a validation error. 将数据设置为实体的一个优点是,如果存在验证错误,它将自动在表单中预填写。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM