Symfony在保存之前检查实体不变量

时间:2015-03-11 15:08:31

标签: symfony doctrine-orm

我有一个课程安排应用程序。

“一个人在被分配之前必须申请当前学期”。

分配有很多学期的周。学期一周有一个学期。 分配有一个人。 申请有一个人。

我的'代码思想'是将其添加到分配实体。它显然不起作用,因为在实体中使用实体管理器是错误的。

/**
 * Invariant is that a person must have a valid application for the specified semester.
 *
 * @ORM\PrePersist()
 * @ORM\PreUpdate()
 */
 public function validatePersonApplication() {
    $semester = $this->getSemesterWeek()->getSemester();
    $existing_application = $em->getRepository("CamsBundle:Application")->findOneBy(
  array(
        'person' => $this->person,
        'semester' => $semester
    )
  );

  if (!is_object($existing_application))  {
      throw new Exception("Can't allocate a session to a person without an application.");
   }
}

如何在保存之前测试这种情况?

1 个答案:

答案 0 :(得分:0)

我遵循Vadim的建议并创建了一项服务。但请注意,这对于扩展域名并不是很好,因为symfony确保有一个单一的实例'因此,作为业务逻辑一部分的任何瞬态数据都无法真正进入服务领域。

我仍然需要进入内核以获取容器来调用服务。我的更新后数据库事件监听器。

运行调试器,看起来好像只处理了一个PrePersist事件。所有操作都是从一个函数触发的。

实体方法

/**
 * Automatically update the updated time.
 *
 * @ORM\PrePersist()
 * @ORM\PreUpdate()
 */
public function updateUpdated() {
  $this->setUpdated(new DateTime());

  // Validate class
  $this->_validateClassSession();

  global $kernel;

  if ('AppCache' == get_class($kernel)) {
    $kernel = $kernel->getKernel();
  }

  $allocationValidator = $kernel->getContainer()->get('allocation_invariants');
  $allocationValidator->validatePersonApplication($this->semesterWeek, $this->person);
}

在services.yml中设置

allocation_invariants:
  class: Interlated\CamsBundle\Services\AllocationInvariants
  arguments: ['@logger', '@doctrine.orm.entity_manager']

'服务'实施

namespace Interlated\CamsBundle\Services;

use Doctrine\ORM\EntityManager;
use Exception;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Interlated\CamsBundle\Entity\SemesterWeek;
use Interlated\CamsBundle\Entity\Person;

class AllocationInvariants {

public function __construct(LoggerInterface $logger, EntityManager $entityManger) {
  $this->logger = $logger;
  $this->entityManager = $entityManger;
}

 /**
 * Invariant is that a person must have a valid application for the specified semester.
 *
 */
 public function validatePersonApplication(SemesterWeek $semesterWeek, Person $person) {
   $semester = $semesterWeek->getSemester();
   $existing_application = $this->entityManager->getRepository("UnswCamsBundle:Application")->findOneBy(
   array(
    'person' => $person,
    'semester' => $semester
   )
 );

 if (!is_object($existing_application))  {
  throw new Exception("Can't allocate a session to a person without an application.");
 }
 }
}

此不变量仍在域类中,因为它不需要进行查询

/**
 * Invariant is that the semester week must be for a semester that this course is allocated to.
 *
 * It looks as though multiple PrePersist() annotations don't work. Only the first is being fired.
 */
protected function _validateClassSession() {
    $semester = $this->getSemesterWeek()->getSemester();
    $courseSemesters = $this->classSession->getTeachingClass()->getCourse()->getSemesters();
    foreach($courseSemesters as $courseSemester) {
      if ($semester == $courseSemester) {return;}
    }

    // Failed to match the course to the current semester.
    $course_semester_names = "";
    foreach($courseSemesters as $courseSemester) {
      $course_semester_names .= $courseSemester->getName() . " ";
    }

    throw new Exception("Trying to make an allocation to a course that is not running in the specified semester. SemesterWeekNumber "
      . $this->semesterWeek->getNumber() . " with semester " . $semester->getName() . " The course is running in the following semesters : " . $course_semester_names);
 }