gpt4 book ai didi

重叠日期的 Symfony2 自定义约束

转载 作者:行者123 更新时间:2023-12-03 19:59:57 25 4
gpt4 key购买 nike

我有一个如下所述的学说实体:

company\MyBundle\Entity\ProgramGrid:
type: entity
table: program_grid
id:
id_program_grid:
type: integer
generator: {strategy: IDENTITY}
fields:
name:
type: text
nullable: true
start_date:
type: date
nullable: false
end_date:
type: date
nullable: true

我想添加一个验证约束女巫验证
start_date 和 end_date 不会与另一条记录重叠。

如果我有 2 条记录 A 和 B,我想要:

B.start_date > A.end_date



实现这一目标的最佳方法是什么?

最佳答案

我刚刚实现了这样的约束及其验证器。这是它的样子:

约束:

<?php

namespace AppBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
* @Annotation
*/
class NotOverlapping extends Constraint
{
public $message = 'This value overlaps with other values.';

public $service = 'app.validator.not_overlapping';

public $field;

public $errorPath;

public function getRequiredOptions()
{
return ['field'];
}

public function getDefaultOption()
{
return 'field';
}

/**
* The validator must be defined as a service with this name.
*
* @return string
*/
public function validatedBy()
{
return $this->service;
}

/**
* @return string
*/
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
}

验证器:

<?php

namespace TriprHqBundle\Validator\Constraints;

use Doctrine\Common\Collections\Criteria;
use Doctrine\Common\Persistence\ManagerRegistry;
use League\Period\Period;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class NotOverlappingValidator extends ConstraintValidator
{
/**
* @var ManagerRegistry
*/
private $registry;

/**
* NotOverlappingValidator constructor.
* @param ManagerRegistry $registry
*/
public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;
}

/**
* @param object $entity
* @param Constraint $constraint
*
* @throws UnexpectedTypeException
* @throws ConstraintDefinitionException
*/
public function validate($entity, Constraint $constraint)
{
if (!$constraint instanceof NotOverlapping) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\NotOverlapping');
}

if (!is_null($constraint->errorPath) && !is_string($constraint->errorPath)) {
throw new UnexpectedTypeException($constraint->errorPath, 'string or null');
}

$em = $this->registry->getManagerForClass(get_class($entity));

if (!$em) {
throw new ConstraintDefinitionException(sprintf('Unable to find the object manager associated with an entity of class "%s".', get_class($entity)));
}

/* @var $class \Doctrine\Common\Persistence\Mapping\ClassMetadata */
$class = $em->getClassMetadata(get_class($entity));

if (!array_key_exists($constraint->field, $class->embeddedClasses)) {
throw new ConstraintDefinitionException(sprintf(
'The field "%s" is not a Doctrine embeddable, so it cannot be validated for overlapping time periods.',
$constraint->field
));
}

$value = $class->reflFields[$constraint->field]->getValue($entity);

if (!is_null($value) && !($value instanceof Period)) {
throw new UnexpectedTypeException($value, 'null or League\Period\Period');
}

if(is_null($value)) {
return;
}

// ... WHERE existing_start < new_end
// AND existing_end > new_start;
$criteria = new Criteria();
$criteria
->where($criteria->expr()->lt(sprintf('%s.startDate', $constraint->field), $value->getEndDate()))
->andWhere($criteria->expr()->gt(sprintf('%s.endDate', $constraint->field), $value->getStartDate()))
;

$repository = $em->getRepository(get_class($entity));
$result = $repository->matching($criteria);

if ($result instanceof \IteratorAggregate) {
$result = $result->getIterator();
}

/* If no entity matched the query criteria or a single entity matched,
* which is the same as the entity being validated, there are no
* overlaps.
*/
if (0 === count($result) || (1 === count($result) && $entity === ($result instanceof \Iterator ? $result->current() : current($result)))) {
return;
}

$errorPath = $constraint->errorPath ?: $constraint->field;

$this->context->buildViolation($constraint->message)
->atPath($errorPath)
->addViolation()
;
}
}

您可以与示例实体一起找到它 in my gist .

关于重叠日期的 Symfony2 自定义约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19546020/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com