【问题标题】:Why Doctrine 2 not have basic validate method that validate if all values fit entities attributes?为什么 Doctrine 2 没有基本的验证方法来验证所有值是否符合实体属性?
【发布时间】:2013-01-29 13:42:05
【问题描述】:

我是第 2 条教义的新手。

为什么 Doctrine 2 没有基本的验证方法来验证所有值是否符合实体属性?

我的问题旨在更多地了解教义 2 的工作原理,以及为什么不说教义 2 中的问题。(主要是因为我是新手,我错过了对教义 2 设计方式的一些理解)

示例:

<?php
// entities/User.php
/**
 * @Entity @Table(name="users")
 **/
class User
{
    /**
     * @Id @GeneratedValue @Column(type="integer")
     * @var int
     **/
    protected $id;

    /**
     * @Column(type="string")
     * @var string
     **/
    protected $name;

}

使用build in validate的代码示例(不需要连接db,只验证@Column(type="integer"))基本功能在教义2中不存在:

$user=new User();
$user->setId('trtr');
$user->setName("goodname");
if($user->validate()){
  echo 'ok';
}
else{
  echo $user->validateError();
}

//output: id of User should be integer and not string

谢谢

【问题讨论】:

  • 我在问教义-project.org/blog/doctrine2-validations.html 中的问题之前看过。但是在教义中没有内置验证方法,只有不使用实体属性定义的自定义方法。还是我错过了什么?
  • 确实没有内置验证。
  • 所以我问为什么?如果实体属性定义了列类型等。为什么不将它们用于基本验证?
  • 我们不会将 Doctrine 2 与任何验证器一起发布,原因是我们认为所有框架都已经发布了相当不错的框架,可以轻松集成到您的域中。除了我们是不想维护另一个验证库的 ORM 专家之外,将验证的责任转移到领域层还可以让您更轻松地将其集成到框架表单库中。

标签: orm doctrine doctrine-orm datamapper


【解决方案1】:

Doctrine ORM 假定您持久化的实体处于有效状态。这是持久层的唯一工作,向它添加验证是错误的。如果您的实体中包含无效数据,则您已经拥有不应保存的无效对象图。

所以请记住,如果你曾经有过类似的 API

$someEntity->isValid();

那么可能有问题,因为实体应该始终有效,并且它的任何依赖项都应该在构造时设置并在 setter/getter 中处理,以便对象永远不会达到不一致的状态。

【讨论】:

  • 要对此进行扩展,通常应在控制器中执行数据验证。对于您的特定用例,一个很好的例子是 Symfony 2 如何使用 Form 组件执行数据验证。 symfony.com/doc/2.8/cookbook/doctrine/registration_form.html 因此使用$form-&gt;isValid 而不是$entity-&gt;isValid(),同时允许您指定自定义约束进行验证,保持实体对象代码更简洁、更快。
【解决方案2】:

主要原因是关注点分离。由于实体是相当愚蠢的对象,对世界其他地方知之甚少,因此它们进行验证的能力一开始就受到限制。

例如,您的典型实体无法验证特定属性是否唯一。

也就是说,如果您只想进行基本验证,只需在 setter 中进行即可。

<?php
class MyEntity {

    // ...

    /**
     * @ORM\Column(length="32")
     */
     protected $myProperty;

     public function setMyProperty($prop){
         if (! is_string($prop))
             throw new \InvalidArgumentException('MyEntity::setMyProperty() expects a string!';
         if (strlen($prop) > 32)
             throw new \LengthException('Argument passed to MyEntity::setMyProperty() is too long!');
         $this->myProperty = $prop;
     }

}

此方法可用于强制执行数据类型、长度等。除此之外的任何内容最好在实体内部以外的地方处理。

【讨论】:

    【解决方案3】:

    将实体和验证混用不是一个好主意,但在实体中将此规则作为注释和验证逻辑放在分离的方面验证器类中是有意义的。

    检查它是如何在 Spring 框架中完成的 - http://www.abtosoftware.com/blog/form-validation-using-aspect-oriented-programming-aop-in-spring-framework

    以及如何使用学说2来实现它,然后去 - http://go.aopphp.com/blog/2013/07/21/implementing-logging-aspect-with-doctrine-annotations/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      相关资源
      最近更新 更多