【问题标题】:How to add validation in symfony2 for datetimes after a particular date?如何在 symfony2 中为特定日期之后的日期时间添加验证?
【发布时间】:2014-04-11 19:59:16
【问题描述】:

我正在尝试添加 Symfony 2.1 表单验证,以确保提交的生日在 1900 年 1 月 1 日或之后。

我希望以下日期通过验证:

  • 01/01/1900
  • 1999 年 12 月 20 日
  • 08/20/2002

我希望以下日期验证失败:

  • 12/20/1899
  • 08/08/0971

我尝试在validation.yml 中使用正则表达式:

// src/Company/UsersBundle/Resources/config/validation.yml
        dateOfBirth:
            - NotBlank: { groups: [verifyGenderAndAge] }
            - Date:
                message: "This is not a valid date. Please enter your date of birth in the following format, MM/DD/YYYY."
                groups: [verifyGenderAndAge]
            - Regex:
                pattern: "/\d{1,2}\/\d{1,2}\/(19|20)\d{2}/"
                message: This is not a valid date. Please enter your date of birth after 01/01/1900 in the following format, MM/DD/YYYY.

我使用这个验证器得到的错误是:

关键 - Symfony\Component\Validator\Exception\UnexpectedTypeException: 字符串类型的预期参数,给定对象(未捕获的异常) /Users/user/code/base/api/vendor/symfony/symfony/src/Symfony/Component/Validator/Constraints/RegexValidator.php 第 38 行

我尝试过创建自定义验证器:

约束:

// src/Company/UsersBundle/Validator/Constraints/IsValidBirthdate.php
namespace Company\UsersBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

class IsValidBirthdate extends Constraint
{
    /**
     * @Annotation
     */
    public $message = "This is not a valid date. Please enter your date of birth after 01/01/1900 in the following format, MM/DD/YYYY.";
}

验证器:

// src/Company/UsersBundle/Validator/Constraints/IsValidBirthdateValidator.php
namespace Company\UsersBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class IsValidBirthdateValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        if (get_class($value) != 'DateTime' || !preg_match('/\d{1,2}\/\d{1,2}\/(19|20)\d{2}/', $value->format('m/d/Y'), $matches)) {
            $this->context->addViolation(
                $constraint->message,
                array('%string%' => $value)
            );
        }
    }
}

实体 YAML 文件:

// src/Company/UsersBundle/Resources/config/validation.yml
...
        dateOfBirth:
            - NotBlank: { groups: [verifyGenderAndAge] }
            - Date:
                message: "This is not a valid date. Please enter your date of birth in the following format, MM/DD/YYYY."
                groups: [verifyGenderAndAge]
            - Company\UsersBundle\Validator\Constraints\IsValidBirthdate: ~
...

使用自定义验证器时出错:

在渲染模板期间引发了异常 (“可捕获的致命错误:DateTime 类的对象不能 转换为字符串 /Users/user/code/Company/api/vendor/symfony/symfony/src/Symfony/Component/Translation/IdentityTranslator.php 第 62 行") 在第 276 行的 form_div_layout.html.twig 中。

500 内部服务器错误 - Twig_Error_Runtime

关于如何在 Symfony 2.1 中实现这个验证器有什么想法吗?

【问题讨论】:

  • 我认为您不应该使用正则表达式验证日期,否则您最终可能会得到像 this 这样的正则表达式。 autor
  • 我实际上并没有验证日期本身,只是检查日期的年份,我已经有标准 Symonfy 2 日期验证器
  • 您是否使用与实体链接的表单?还是没有要形成的链接实体?
  • 有一个实体链接到表单

标签: php regex validation symfony datetime


【解决方案1】:

您可以在验证实体时使用自定义Getters

Acme\BlogBundle\Entity\Author:
    getters:
        dateLegal:
            - "True": { message: "Date of birth is not valid" }

并在您的实体中创建一个名为 isDateLegal 的公共 getter 并在此处检查您的日期,不确定 DateTime 语法,但它只是一个展示的想法

public function isDateLegal() /* this can be named as getDateLegal()*/
{
    $datetime = new \DateTime('01/01/1900');
    return $this->date_of_birth <  $datetime->format('Y-m-d') ;
}

$this-&gt;date_of_birth 是实体的属性,您也可以使用您的出生日期属性$this-&gt;getDateOfBirth() &lt; $datetime-&gt;format('Y-m-d')

【讨论】:

    【解决方案2】:

    在第二个错误中,(twig 中的错误 500)可能只是意味着您试图直接从 datetime 对象中获取日期。尝试使用format() 方法获取格式化字符串:

    看这里 http://www.php.net/manual/en/datetime.format.php

    <?php
        $date = new DateTime('2000-01-01');
        echo $date->format('Y-m-d H:i:s');
    ?>
    

    【讨论】:

    • 在 Symfony 中自动创建表单我没有手动打印出值
    • 所以在阅读了您的答案后,我再次查看了我的代码,发现问题出在哪里,我必须更新我的 Validator 类
    • 太棒了!很高兴你找到了答案。
    【解决方案3】:

    您可以使用您的验证器(稍作编辑)创建一个 `\DateTime' 实例,然后将其与提供的字段进行比较。就这样..

    约束

    namespace Company\UsersBundle\Validator\Constraints;
    
    use Symfony\Component\Validator\Constraint;
    
    class DateRange extends Constraint
    {
        /**
         * @Annotation
         */
        public $minMessage = "This value is not valid. 
                                             Please specify a date after {value}.";
    
        public $min;
    
        /**
         * @Annotation
         */
        public $maxMessage = "This value is not valid.
                                             Please specify a date before {value}.";
    
        public $max;
    }
    

    验证器

    namespace Company\UsersBundle\Validator\Constraints;
    
    use Symfony\Component\Validator\Constraint;
    use Symfony\Component\Validator\ConstraintValidator;
    
    class DateRangeValidator extends ConstraintValidator
    {
        public function validate($value, Constraint $constraint)
        {
            if (!$value instanceof \DateTime) {
                return;
            }
    
            if (null !== $constraint->min) {
                $min = $this->convertToDateTime($constraint->min);
    
                if ($value < $min) {
                    $this->context->addViolation(
                        $constraint->minMessage,
                        array('{value}' => $value->format('Y-m-d')
                    );
                }
            }
    
            if (null !== $constraint->max) {
                $max = $this->convertToDateTime($constraint->max);
    
                if ($value > $max) {
                    $this->context->addViolation(
                        $constraint->maxMessage,
                        array('{value}' => $value->format('Y-m-d')
                    );
                }
            }
        }
    
        /**
         * Convert string to \DateTime
         *
         * @param string $field
         * @return \DateTime
         * throw \Exception
         */
        private function convertToDateTime($field)
        {
            try {
                $date = new \DateTime($field);
            } catch (\Exception $e) {
                throw new \Exception(
                    sprintf('Value "%s" is not in a valid "strtotime" format')
                );
            }
    
            return $date;
        }
    }
    

    有了它,您可以使用任何用于创建\DateTime 对象的字符串,例如01/01/2010- 18 years 等。 我不是 100% 确定这会起作用,但我的想法是您可以设置一个最小值或最大值或同时设置两者,然后将提供的值与这些值进行比较。

    注意事项:

    您正在尝试将 \DateTime 对象验证为字符串,由于它是一个对象,这是不可能的,因此您需要相应地对其进行验证。

    【讨论】:

    • 感谢您的反馈,很遗憾我对此没有要求 :-)
    • 你的意思是你没有这方面的要求?您希望生日在特定日期之后,因此您可以将 min 设置为 01/01/1990 或可能是 1990-01-01 以确保正确识别它。使用此验证器,您可以将 min\max 设置为可以在 \DateTime 的 __construct 中使用的任何内容。
    • 这个项目的产品负责人没有为这种类型的功能(最小日期和最大日期)创建任何票,所以我不能这样做
    • “确保提交的生日在 1900 年 1 月 1 日或之后”听起来很像最低日期情况,但抱歉我帮不上忙。
    【解决方案4】:
    猜你喜欢
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-09
    • 1970-01-01
    • 2023-03-17
    • 2017-04-22
    • 1970-01-01
    相关资源
    最近更新 更多