Symfony 在保存前检查实体不变性
Symfony checking entity invariant before saving
我有一个课程安排应用程序。
"A person must have an application for the current semester before being allocated"。
分配有很多学期周。学期周有一个学期。
分配有一个人。
申请1人
我的'code thought'是把这个加到分配实体里。显然是行不通的,因为在实体中使用实体管理器是错误的。
/**
* 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.");
}
}
保存前如何测试这个条件?
我按照 Vadim 的建议创建了一个服务。但是请注意,这对于将域扩展为 'symfony ensures there is a single instance' 并不是很好,因此作为业务逻辑一部分的任何瞬态数据都不能真正进入服务。
我仍然需要进入内核以使容器调用服务。我的 post-更新数据库事件侦听器。
运行 调试器,看起来好像只处理了一个 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']
'service' 实现
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.");
}
}
}
此不变量仍在域中class,因为它不需要进行查询
/**
* 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);
}
我有一个课程安排应用程序。
"A person must have an application for the current semester before being allocated"。
分配有很多学期周。学期周有一个学期。 分配有一个人。 申请1人
我的'code thought'是把这个加到分配实体里。显然是行不通的,因为在实体中使用实体管理器是错误的。
/**
* 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.");
}
}
保存前如何测试这个条件?
我按照 Vadim 的建议创建了一个服务。但是请注意,这对于将域扩展为 'symfony ensures there is a single instance' 并不是很好,因此作为业务逻辑一部分的任何瞬态数据都不能真正进入服务。
我仍然需要进入内核以使容器调用服务。我的 post-更新数据库事件侦听器。
运行 调试器,看起来好像只处理了一个 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']
'service' 实现
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.");
}
}
}
此不变量仍在域中class,因为它不需要进行查询
/**
* 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);
}