最佳实践 - 在持久化之前检查实体是否存在

时间:2014-02-09 06:13:33

标签: symfony symfony-forms

在持久化之前检查实体字段是否存在的最佳做法是什么。 这是一个例子 实体

class Pile{
    /**
    * @var \ABC\CoreBundle\Entity\Record
    *
    * @ORM\OneToMany(targetEntity="Record")
    *
    */
    private $records;

    /**
    * @var \CSC\CoreBundle\Entity\Project
    *
    * @ORM\ManyToOne(targetEntity="Project")
    *
    */
    private $project;

    /**
    * @var string
    *
    * @ORM\Column(name="Block", type="string", length=255)
    */
   private $block;

   /**
   * @var string
   *
   * @ORM\Column(name="Type", type="string", length=255)
   */
   private $type;

}

class Record{
    /**
    * @var \CSC\CoreBundle\Entity\Pile
    *
    * @ORM\ManyToOne(targetEntity="Pile")
    *
    */
    private $records;
}

有两个控制器可以处理桩和记录的CRUD。 要创建桩,必须没有任何重复的字段[项目,块,类型]

在记录控制器中,我可以与记录一起创建桩。

如果创建了类似的桩实体,我在何时何地检查数据库? 什么是最佳实践?

  1. 将查询检查器复制并粘贴到两个控制器中?
  2. 我可以使用$ form-> valid()来执行PileType类中的任何检查吗?
  3. 我必须使用服务并让两个控制器都可以调用该服务吗?
  4. 在实体生命周期中使用预插入?
  5. 由于

2 个答案:

答案 0 :(得分:3)

您可以在表单中使用自定义验证约束,以便$form->isValid()进行检查。 按照How to create a Custom Validation Constraint上的此文档条目创建自定义验证器,然后将原则注入其中以进行检查。

更新:好吧,我不知道Symfony中已经包含UniqueEntity约束。

要注入学说,请执行以下操作:

services:
    validator.unique.unique_pile:
        class: ABC\CoreBundle\Validator\Constraints\UniquePileValidator
        arguments: [@doctrine.orm.entity_manager]
        tags:
            - { name: validator.constraint_validator, alias: unique_pile }

验证器类可能如下所示:

// src/ABC/CoreBundle/Validator/Constraints/UniquePileValidator.php
namespace ABC\CoreBundle\Validator\Constraints;

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

class UniquePileValidator extends ConstraintValidator
{
    protected $em;

    function __construct($em) {
        $this->em = $em;
    }

    public function validate($value, Constraint $constraint)
    {
        $repo = $this->em->getRepository('ABC\CoreBundle\Entity\Record');

        $duplicate_project = $repo->findByProject($value);
        $duplicate_block = $repo->findByBlock($value);
        $duplicate_type = $repo->findByType($value);

        if ($duplicate_project || $duplicate_block || $duplicate_type) {
            $this->context->addViolation(
                $constraint->message,
                array('%string%' => $value)
            );
        }
    }
}

完成后,约束类:

// src/ABC/CoreBundle/Validator/Constraints/ContainsAlphanumeric.php
namespace ABC\CoreBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class ContainsAlphanumeric extends Constraint
{
    public $message = 'This Pile already exists!';

    public function validatedBy()
    {
        return 'unique_pile';
    }
}

应该几乎可以复制/粘贴......

答案 1 :(得分:3)

因此,字段必须是唯一的?

如果是这样,那么很简单:UniqueEntity

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
...

/**
 * @ORM\Entity
 * @UniqueEntity(
 *     fields={"project", "block", "type"}
 * )
 */
class Pile{
    /**
    * @var \ABC\CoreBundle\Entity\Record
    *
    * @ORM\OneToMany(targetEntity="Record")
    *
    */
    private $records;

    /**
    * @var \CSC\CoreBundle\Entity\Project
    *
    * @ORM\ManyToOne(targetEntity="Project")
    *
    */
    private $project;

    /**
    * @var string
    *
    * @ORM\Column(name="Block", type="string", length=255, unique=true)
    */
   private $block;

   /**
   * @var string
   *
   * @ORM\Column(name="Type", type="string", length=255, unique=true)
   */
   private $type;

}