Symfony — проверка нескольких элементов в форме Collection

Итак, у меня есть форма, в которой есть коллекция, и пользователь может добавлять новые элементы в эту коллекцию. Моя сущность в этой коллекции имеет идентификатор и целое число. Я хочу проверить, что пользователь не может добавить элемент за другим, который имеет более низкое целое число, чем первый.

Например, форма пуста, пользователь добавляет запись в коллекцию, нажав на кнопку Добавить. Он вводит 100 в поле ввода и добавляет еще одну запись и вводит 50 в поле ввода. Когда он пытается отправить сообщение, я хочу, чтобы во второй записи была ошибка, потому что 50 меньше 100, но он добавил ее в список после.

Вот мои FormTypes и Entites

class ItemType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('value');
}
}

class ItemCollectionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('items', 'collection', array(
'type' => new ItemType(),
'allow_add'    => true,
'allow_delete' => true,
'by_reference' => false,
'label' => false,
));

$builder->add('save');
}
}

class Item
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;

/**
* @ORM\Column(type="integer", nullable=true)
*/
protected $value;
}

class List
{
/**
* @ORM\OneToMany(targetEntity="Item", cascade={"persist"})
* @Assert\Valid
**/
private $items;
}

Я думаю, что я мог бы сделать проверку в контроллере, но я хотел бы сделать это в моей сущности и с использованием проверки или пользовательской проверки.

** РЕДАКТИРОВАТЬ **

Я также могу сделать то, что предложил ДонКаллисто, но я пытаюсь получить ошибку в конкретной строке, которая вызывает проблемы, а не только в глобальном классе, как он предложил.

Я не могу найти, как добавить propertyPath к проблемному элементу, я попытался использовать следующий код, но кажется, что он по-прежнему связывает ошибку с классом, а не с самим элементом, как хотелось бы.

$context->addViolationAt(
$context->getPropertyPath().'.items.data.value',
'Your violation message'
);

Это также не принимает во внимание текущий элемент.

Следующий код тоже не работает. Здесь я жестко кодирую ключ массива только для целей тестирования.

$context->addViolationAt(
$context->getPropertyPath().'.items[0].data.value',
'Your violation message'
);

Может кто-нибудь сказать мне, как правильно настроить путь для доступа к значению ребенка в коллекции?

2

Решение

Я нашел ответ на свой вопрос, использовал часть ответа ДонКаллисто и переместил код из List Сущность к Item и в валидаторе, который я называю как CLASS_CONSTRAINT на моем Item Сущность.

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

/**
* @Annotation
*/
class ItemsOrderedValidator extends ConstraintValidator  {

public function validate($value, Constraint $constraint) {
foreach ($value->getList()->getItems() as $item) {
$currentValue = $item->getValue();

if (isset($prevValue) && $prevValue >= $currentValue && $value === $item) {
$this->context->buildViolation($constraint->message)
->atPath('value')
->addViolation();
}
$prevValue = $currentValue;
}
}
}
2

Другие решения

Если я правильно понял ваш вопрос, вы можете изменить свой объект List следующим образом

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\ExecutionContext;

/**
* //Whatever you have here to declare this as an entity
* @Assert\Callback(methods={"areItemsOrdered"})
*/
class List
{
/**
* @ORM\OneToMany(targetEntity="Item", cascade={"persist"})
* @Assert\Valid
**/
private $items;

//whatever methods you have here

public function areItemsOrdered(ExecutionContext $context)
{
foreach ($this->items as $item) {
$current_value = $item->getValue();

if (!isset($prev_value)) {
$prev_value = $current_value;
} else {
if ($prev_value > $current_value) {
$context->addViolation('Your violation message');
}
}
}
}
}

Для получения дополнительной информации о методах обратного вызова объекта: http://symfony.com/doc/2.3/reference/constraints/Callback.html

Для получения дополнительной информации о ExecutionContext: http://api.symfony.com/2.4/Symfony/Component/Validator/ExecutionContextInterface.html

КСТАТИ

Правильное ли поведение для информирования пользователя об ошибке? Я имею в виду, вы не могли бы сортировать добавленные элементы самостоятельно?
Если это так, пожалуйста, обновите свой ответ, и я буду рад обновить мой код для этой цели.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector