Подтвердить что ты не робот

Cascade Validation не работает над третьим слоем формы

У меня есть форма с тремя слоями: Первый слой - это контейнер для игр:

class GameListType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->add('games', 'collection', array(
            'required' => false,
            'allow_add' => true,
            'prototype' => true,
            'by_reference' => false,
            'type' => new GameBetType(),
        ))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver) {
        parent::setDefaultOptions($resolver);
        $resolver->setDefaults(array(
            'cascade_validation' => true,
        ));
    }  
}

Второй слой - сама игра, так как я не намерен менять игру, но ставка на нее включает только форму для ставки:

class GameBetType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {   
        $builder->add('bet', new BetType());
    }

    public function setDefaultOptions(\Symfony\Component\OptionsResolver\OptionsResolverInterface $resolver) {
        parent::setDefaultOptions($resolver);
        $resolver->setDefaults(array(
            'data_class' => 'Strego\TippBundle\Entity\Game',
            'cascade_validation' => true,
        ));
    }  
}

И третий слой - это форма для ставки:

class BetType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder->add('scoreT1' , 'text')
                ->add('scoreT2' , 'text');
        ;
    }


        public function setDefaultOptions(\Symfony\Component\OptionsResolver\OptionsResolverInterface $resolver) {
        parent::setDefaultOptions($resolver);
        $resolver->setDefaults(array(
            'data_class' => 'Strego\TippBundle\Entity\Bet',
        ));
    }

}

Проблема заключается в том, что если на третьем уровне есть ограничения проверки, корневая форма всегда действительна, но если я специально проверяю объект ставки, я получаю правильный список нарушений в моем контроллере:

// Form processing
$form = $this->createForm(new GameListType(), $entity);
$request = $this->getRequest();

if ($request->getMethod() == 'POST') {
    $form->bind($request);
    $entity = $form->getData();

    if ($form->isValid()) {
        foreach ($entity->getGames() as $game) {                  
            if($game->hasBet()){
                $bet = $game->getBet();
                $bet->setUser($user);
                $validator = $this->container->get('validator');
                $errors = $validator->validate($bet);
                var_dump($errors)  //<-- i see there are errors
                if(count($errors) == 0){
                    print($bet. ' gets persisted<br>');
                    $em->persist($bet);
                } 
            }             
        }
    $em->flush();
    }
}

Другая проблема заключается в том, что даже если я не вызываю $em->persist($bet), сущности остаются. Я не вижу выхода, описанного в строке

print($bet.'gets persisted<br>'); 

но ввод формы сохраняется в базе данных.

Итак, мои два вопроса:

  • Как я могу получить ошибки, если проверка завершилась неудачно в отношении ставки, не соответствует форме (я не хочу, чтобы вся форма была недействительной, так как только одна из трех ставок недействительна).

  • Почему ставка сохраняется, даже если я не звоню $em-persist($bet), это какая-то магия, которая происходит со связыванием?

4b9b3361

Ответ 1

Чтобы ответить на второй вопрос, вы могли заявить двунаправленную связь OneToMany между User и Bet сущностью и установить cascade={"persist"} на стороне User. Таким образом, менеджер объектов автоматически помещает объекты объекта Bet для вставки/обновления в следующей операции flush. Также перемещайте строку $em->flush(); из цикла. Поскольку метод flush выдает запрос db, он подключается к db каждый раз, когда код входит в цикл. Если $em->flush(); находится за пределами цикла, объект будет запрашивать один раз со всеми измененными sql, заключенными в одну транзакцию.

Ответ 2

Вы просто забыли добавить cascade_validation в игры collection type

$builder->add('games', 'collection', array(
    'required' => false,
    'allow_add' => true,
    'prototype' => true,
    'by_reference' => false,
    'type' => new GameBetType(),
    'cascade_validation' => true
));

Ответ 3

Я уверен, что вы должны сохранить объект game, а не bet.

Для проверки правильности установки какой-либо группы проверок это может быть причиной неправильной проверки правильности.