Codeigniter - 日期格式 - 表单验证

15

我正在使用 CodeIgniterPHP。 我正在使用以下表单,

<?php
    echo form_open('/register/create_new', $form_params);
?>

DOB: <input type="text" id="dob" name="reg[dob]">
     <input type="submit" value="Create Account" />
</form>

这里,#dob 是以 dd-mm-yyyy 格式表示的。

我的验证代码是:

array(
  'field' => 'reg[dob]',
  'label' => 'DOB',
  'rules' => 'required'
)

我该如何设置正确的日期验证规则


如果可能的话,考虑为日、月、年使用单独的下拉菜单。这样可以减少用户出错的机会,特别是在月份和日期混淆的情况下。 - cartalot
1
@cartalot 但是,我正在使用jQuery日期选择器。 - KarSho
10个回答

22
我有一个相当简单的解决方案。你可以扩展CodeIgniter表单验证库。
在应用程序/ libraries文件夹中放置MY_Form_validation.php文件来实现这个目的。此文件应如下所示:
class MY_Form_validation extends CI_Form_validation {

    public function __construct($rules = array()) {
        parent::__construct($rules);
    }


    public function valid_date($date) {
        $d = DateTime::createFromFormat('Y-m-d', $date);
        return $d && $d->format('Y-m-d') === $date;
    }
}

为添加错误信息,您需要前往应用程序的 language/ 目录并打开 form_validation_lang.php 文件。在文件末尾向 $lang 数组添加一个条目,例如:

$lang['form_validation_valid_date'] = 'The field {field} is not a valid date';

请注意,这里的key必须与函数名(valid_date)相同。

然后在控制器中,您可以像使用其他表单验证函数一样使用它,比如'required'。

$this->form_validation->set_rules('date','Date','trim|required|valid_date');

4
这是一个非常优雅的解决方案,我建议添加一个参数以允许更好的自定义。 为日期格式添加一个参数:function valid_date($date, $format = 'Y-m-d') 并在函数中引用它。您可以在验证规则中传递此参数,例如:'trim|required|valid_date[d-m-y]' 然后,lang文件可以使用{param}来指定错误时预期的格式。 - CYMA
https://dev59.com/QWnWa4cB1Zd3GeqP15KQ - Sushant Pimple
1
加一点漂亮的标准方式......还需要添加格式参数。 - Imran Qamer
1
这绝对是最好的答案! - Pieter-Jan Casteels
这绝对应该是被接受的答案。漂亮、优雅、标准化。 - Javier Larroulet
很好的全面解决方案!我只是将valid_date函数更改为:return (bool)strtotime($date);以涵盖所有情况。 - Dario Zadro

22
您可以利用CodeIgniter回调函数,通过创建一个callback_date_valid()函数来检查日期是否有效。
为了检查日期是否有效,您可以使用PHP的checkdate函数
array(
  'field' => 'reg[dob]',
  'label' => 'DOB',
  'rules' => 'required|date_valid'
)

function callback_date_valid($date){
    $day = (int) substr($date, 0, 2);
    $month = (int) substr($date, 3, 2);
    $year = (int) substr($date, 6, 4);
    return checkdate($month, $day, $year);
}

1
使用适当的日期函数是正确的方法。很好的答案。 - Álvaro González
2
我认为这也是正确的方法。但是有一点,函数的名称必须没有“callback”。因此,正确的方式应该是> function date_valid($date){ - Limon

9

你可以使用 正则表达式 来完成。

$this->form_validation->set_rules('reg[dob]', 'Date of birth', 'regex_match[(0[1-9]|1[0-9]|2[0-9]|3(0|1))-(0[1-9]|1[0-2])-\d{4}]'); 

4
使用正则表达式无法实现可靠的日期验证。你提供的正则表达式其实已经很不错了,但例如它认为 29-02-2000 不是一个有效日期。 - Álvaro González
@ÁlvaroG.Vicario 我认为使用“正则表达式”也是可能的。 - Abin Manathoor Devasia
3
如果你有耐心,你可能可以硬编码所有的异常情况(包括由于转换为公历而遗漏的日期),但你知道我想说什么:正则表达式并不是最好的工具。 - Álvaro González
@ÁlvaroG.Vicario https://dev59.com/2moy5IYBdhLWcg3wScLb?answertab=active#tab-top - Abin Manathoor Devasia
1
这个正则表达式格式不起作用。我不得不用/.../来包含模式。而且,我无法让这个模式工作。regex_match[/\d{4}-\d{2}-\d{2}/]似乎可以工作,但是regex_match[/\d{4}-(0[1-9]|1[0-2])-\d{2}/]不能。我将坚持使用回调方法。 - akinuri

2

Codeigniter的form_validation库中没有内置日期验证功能,但是您可以利用其回调函数来调用函数并使用PHP自己的能力进行日期验证。

使用DateTime,您可以制作适用于所有格式的最短日期和时间验证器。

function validateDate($date, $format = 'Y-m-d H:i:s')
{
    $d = DateTime::createFromFormat($format, $date);
    return $d && $d->format($format) == $date;
}

var_dump(validateDate('2012-02-28 12:12:12')); # true
var_dump(validateDate('2012-02-30 12:12:12')); # false
var_dump(validateDate('2012-02-28', 'Y-m-d')); # true
var_dump(validateDate('28/02/2012', 'd/m/Y')); # true
var_dump(validateDate('30/02/2012', 'd/m/Y')); # false
var_dump(validateDate('14:50', 'H:i')); # true
var_dump(validateDate('14:77', 'H:i')); # false
var_dump(validateDate(14, 'H')); # true
var_dump(validateDate('14', 'H')); # true

var_dump(validateDate('2012-02-28T12:12:12+02:00', 'Y-m-d\TH:i:sP')); # true
# or
var_dump(validateDate('2012-02-28T12:12:12+02:00', DateTime::ATOM)); # true

var_dump(validateDate('Tue, 28 Feb 2012 12:12:12 +0200', 'D, d M Y H:i:s O')); # true
# or
var_dump(validateDate('Tue, 28 Feb 2012 12:12:12 +0200', DateTime::RSS)); # true
var_dump(validateDate('Tue, 27 Feb 2012 12:12:12 +0200', DateTime::RSS)); # false

该函数是从此答案php.net复制而来的。


2

我知道这个问题很旧了,但我刚遇到同样的问题。我喜欢Winks提供的答案,但发现代码无法工作。我对其进行了修改:

  public function your_form_handler($date)
  {
    // ....
    $this->form_validation->set_rules('date', 'Date', 'required|callback_date_valid');
    // ....
  }

  /**
   * Validate dd/mm/yyyy
   */
  public function date_valid($date)
  {
    $parts = explode("/", $date);
    if (count($parts) == 3) {      
      if (checkdate($parts[1], $parts[0], $parts[2]))
      {
        return TRUE;
      }
    }
    $this->form_validation->set_message('date_valid', 'The Date field must be mm/dd/yyyy');
    return false;
  }

我觉得这很有用。但它也验证了21/07/1yyy,即一个数字年份也是被验证的。 - Dayz

1
尝试这个...我认为它更简单。

$this->form_validation->set_rules('date', 'Date', 'trim|required|callback_checkDateFormat');

function checkDateFormat($date) {
        $d = DateTime::createFromFormat('Y-m-d', $date);
        if(($d && $d->format('Y-m-d') === $date) === FALSE){
            $this->form_validation->set_message('checkDateFormat', ''.$date.' is not a valid date format.');
            return FALSE;
        }else{
            return TRUE;
        }
}

0

Codeigniter日期验证的正则表达式:

$this->form_validation->set_rules('reg[dob]','Date of birth',array('regex_match[/^((0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.](19|20)\d\d)$/]'));

我正在使用相同的表达式来格式化dd-mm-yyyy和dd/mm/yyyy

没有警告和错误:-)


0
根据iamyojimbo的回答,
    $date = [
        '28.02.2012', // true
        '28/02/2012', // true
        '28-02-2012', // true
        '28 02 2012', // true
        '28 02 1812', // false
    ];

    $pattern = '/^(0[1-9]|[12][0-9]|3[01])[\.\/\-\ ](0[1-9]|1[012])[\.\/\-\ ](19|20)\d\d$/';

    foreach ($date as $subject) {
        print_r(
            preg_match(
                $pattern,
                $subject
            )
        );
    }

0
我已经为ci3编写了这个自定义验证器 - 验证d/m/Y H:i格式 - 你可以轻松更改它。
$this->form_validation->set_rules("start_date", "Start Date", 'trim|callback__check_date_valid');


   public function _check_date_valid($date){

    $this->form_validation->set_message('_check_date_valid', "Please enter a valid date");
    $d = DateTime::createFromFormat('d/m/Y H:i', $date);

    if($d && $d->format('d/m/Y H:i') === $date || $date == ''){
        return true;
    }else{

        return false;
    }

}

除非你擅长正则表达式 - 否则这种方法更安全,可以明确设置 PHP 日期格式以进行验证。 - Edmunds22

0

我喜欢tmsimont提供的答案,但发现如果输入非数字值,代码无法正常工作。修改后的代码如下:

/**
    * Validate dd/mm/yyyy
    */
    public function date_valid(){
        $date=$this->input->post('dob');
        $parts = explode("/", $date);
        if (count($parts) == 3) {     
            if (is_numeric($parts[2])) {  
                if (is_numeric($parts[0])) {
                    if (is_numeric($parts[1])) {    
                        if (checkdate($parts[1], $parts[0], $parts[2])){
                            return TRUE;
                        }
                    }
                }
            }
        }

        $this->form_validation->set_message('date_valid', 'The Date field must be mm/dd/yyyy');
        return false;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接