2

这一集来自 ElePHPant 的声音,在Zend_Form22:00左右开始讨论Zend\FormZend Framework 2 中的内容。

过滤和验证附加到模型而不是绑定到表单,这允许在模型级别拥有业务规则(验证和过滤)。

我正在使用 Zend Framework 1.11 进行开发,并且我的模型是 Doctrine 2.2 实体:如何将过滤器和验证链附加到我的实体?我想验证实体@LifecycleCallbacks或将过滤和验证附加到实体本身。这样,无论数据来自何处(来自 Web 表单上下文或来自 Web 服务甚至命令行上下文),我都可以在将数据刷新到数据库之前对其进行验证。

任何帮助和代码示例将不胜感激。谢谢!

4

4 回答 4

2

根据我对 ZF2 Forms RFC http://framework.zend.com/wiki/display/ZFDEV2/RFC++-+Forms的了解,您可以通过在属性上声明过滤器/验证注释来注释模型/实体。

然后,您必须将模型绑定到表单对象,表单将读取并将任何相关注释应用于自身。我在这个实现中看到的一个问题是,仍然没有真正分离验证/过滤逻辑,因为这些定义被封装在您的表单对象中。

什么会更好(我不知道这是否在管道中)是表单对象调用模型上的验证例程。当然,它可能是模拟 Form 组件在您的模型中所做的事情(通过阅读注释)并在本地应用它(在 ZF2 中)。这个组件目前正在开发中,所以我肯定有兴趣在它接近完成时播放。

无论如何,对于 ZF 1.11(我自己也使用过这个实现),您可以在模型中定义验证例程,并且 $model->validate() 生成的任何错误消息都可以注入到 Zend Form 错误堆栈中。

// element
$form->getElement('my_element')->addErrors($model->getErrorMessages());

// form
$form->addErrors($model->getErrorMessages());

所以你最终会得到一个类似的实现;

$form = new My_Form();
if ($this->_request->_isPost())
{
   $data = $this->_request->getPost();
   $model = new \Entities\MyModel();
   $model->populate($data);
   if (!$model->isValid())
   {
      $form->addErrors($model->getErrorMessages());
   }
   if ($form->isValid())
   {
      // continue to save the model etc...
   }
}
于 2012-04-19T11:04:40.843 回答
0

首先,我要感谢大家的回答,我保证我会尝试你们的解决方案,看看什么适合我。其次,我发现这个:http ://www.spiffyjr.me/2011/07/15/more-doctrine-2-and-zend-framework-integration-goodies/当然还有那篇文章中的公司github,https:/ /github.com/SpiffyJr/Spiffy这看起来像是我的问题的解决方案,但我不知道它在生产中是否稳定,或者是否会进一步改进/开发,但下次我也会尝试。而且我想我的问题的另一个答案可能是在 zend 框架 1.X 中使用 symfony 验证器和教义 2

于 2012-04-19T13:55:57.453 回答
0

这很棘手,但如果您想使用 Zend Framework 1.X 构建类似的东西,您可能必须扩展Zend_Form.

您可以通过这种方式构建一个接受EntityManager(或泛型Doctrine\Common\Persistence\ObjectManager作为依赖项以及实体的类)。

然后,您可以分析与您的实体关联的元数据,或者定义一组必须针对该实体进行检查的字段。通常,您所做的是与Doctrine\Common\Persistence\Mapping\ClassMetadata构造函数中的以下实例进行交互:

// in class Your\Form\EntityDriven
// $this->em is the EntityManager passed in
// $this->entity is the Entity object passed to the constructor
$class = $this->em->getClassMetadata(get_class($this->entity));
foreach ($class->getFieldNames() as $fieldName) {
    // Add fieldst to the form based by their eventual @Column(type="...")
    // Eventually, you could use your own AnnotationDriver to get more 
    // constraints as Symfony 2 does
}

那应该确实有效。验证器将附加到表单实例。要保留表单,您可以覆盖persistData公共方法,如下所示:

public function persistData()
{
    $this->em->persist($this->entity);
    $this->em->flush($this->entity);
}

我不会在@postPersistor之类的生命周期事件中进行验证@preUpdate,因为在这些情况下防止持久性的唯一方法是抛出异常(除非您使用外部侦听器,但这更加复杂)。你最终会得到一个封闭的EntityManager.

如果您对 Zend Framework 2 中应用的概念感兴趣,Zend\Form的(参见 diff)组件使用hydrator将值分配给模型,因此它不会直接与它们交互,而是可以使用逻辑来发现 setter/getter 或公共属性(仅作为示例)。输入过滤已Zend\InputFilter作为一个新组件移至,因为它也应该在没有表单的情况下使用(您想要做什么)。验证已经解耦,但一般来说,当数据无效时不应执行 hydrator。所以现在你应该可以写一个EntityHydratorand了EntityValidator。如果你愿意贡献,请在DoctrineModule上做一个 Pull Request :)

于 2012-04-19T09:30:29.063 回答
0
  1. 我的方法如下:

a) 具有验证客户端(Web 表单)和模型,以便在 Web 客户端验证失败或添加其他客户端类型时。

b) 模型中的验证规则也可以进行单元测试,这对于确保规则工作验证以及模式非常有用

  1. 我没有使用 Zend_Form,因为我手动开发所有表单并使用 JQuery 验证插件添加客户端验证 (http://bassistance.de/jquery-plugins/jquery-plugin-validation/)

  2. 在客户端进行所有验证,我还在 Doctrine 2 模型中使用生命周期回调实现了 preInsert 和 preUpdate 方法。

  3. 但是我没有使用 Zend_Validate 类,因为我发现它们太冗长了,所以我选择了 Symfony Validation 类,它可以使用我的 Doctrine 2 模型映射等注释进行配置。更多细节在这里http://ssmusoke.wordpress.com/2012/03/04/doctrine-2-day-2-model-validation-using-symfony-validator-service-in-zend-framework/

于 2012-04-19T09:35:17.110 回答