How can I add a violation to a collection?

后端 未结 3 1093
天命终不由人
天命终不由人 2020-12-10 06:06

My form looks like this:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $factory = $builder->getFormFactory();

    $build         


        
3条回答
  •  醉酒成梦
    2020-12-10 06:30

    I have been wrestling with this issue in Symfony 3.3, where I wished to validate an entire collection, but pass the error to the appropriate collection element/field. The collection is added to the form thus:

            $form->add('grades', CollectionType::class,
                [
                    'label'         => 'student.grades.label',
                    'allow_add'     => true,
                    'allow_delete'  => true,
                    'entry_type'    => StudentGradeType::class,
                    'attr'          => [
                        'class' => 'gradeList',
                        'help'  => 'student.grades.help',
                    ],
                    'entry_options'  => [
                        'systemYear' => $form->getConfig()->getOption('systemYear'),
                    ],
                    'constraints'    => [
                        new Grades(),
                    ],
                ]
            );
    

    The StudentGradeType is:

    om = $om;
        }
    
        /**
         * {@inheritdoc}
         */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('status', SettingChoiceType::class,
                    [
                        'setting_name' => 'student.enrolment.status',
                        'label'        => 'grades.label.status',
                        'placeholder'  => 'grades.placeholder.status',
                        'attr'         => [
                            'help' => 'grades.help.status',
                        ],
                    ]
                )
                ->add('student', HiddenType::class)
                ->add('grade', EntityType::class,
                    [
                        'class'         => Grade::class,
                        'choice_label'  => 'gradeYear',
                        'query_builder' => function (EntityRepository $er) {
                            return $er->createQueryBuilder('g')
                                ->orderBy('g.year', 'DESC')
                                ->addOrderBy('g.sequence', 'ASC');
                        },
                        'placeholder'   => 'grades.placeholder.grade',
                        'label'         => 'grades.label.grade',
                        'attr'          => [
                            'help' => 'grades.help.grade',
                        ],
                    ]
                );
    
            $builder->get('student')->addModelTransformer(new EntityToStringTransformer($this->om, Student::class));
    
        }
    
        /**
         * {@inheritdoc}
         */
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver
                ->setDefaults(
                    [
                        'data_class'         => StudentGrade::class,
                        'translation_domain' => 'BusybeeStudentBundle',
                        'systemYear'         => null,
                        'error_bubbling'     => true,
                    ]
                );
        }
    
        /**
         * {@inheritdoc}
         */
        public function getBlockPrefix()
        {
            return 'grade_by_student';
        }
    
    
    }
    

    and the validator looks like:

    namespace Busybee\Management\GradeBundle\Validator\Constraints;
    
    use Busybee\Core\CalendarBundle\Entity\Year;
    use Symfony\Component\Validator\Constraint;
    use Symfony\Component\Validator\ConstraintValidator;
    
    class GradesValidator extends ConstraintValidator
    {
        public function validate($value, Constraint $constraint)
        {
    
            if (empty($value))
                return;
    
            $current = 0;
            $year    = [];
    
            foreach ($value->toArray() as $q=>$grade)
            {
                if (empty($grade->getStudent()) || empty($grade->getGrade()))
                {
    
                    $this->context->buildViolation('student.grades.empty')
                        ->addViolation();
    
                    return $value;
                }
    
                if ($grade->getStatus() === 'Current')
                {
                    $current++;
    
                    if ($current > 1)
                    {
                        $this->context->buildViolation('student.grades.current')
                            ->atPath('['.strval($q).']')  // could do a single atPath with a value of "[".strval($q)."].status"
                            ->atPath('status')      //  full path = children['grades'].data[1].status
                            ->addViolation();
    
                        return $value;
    
                    }
                }
    
                $gy = $grade->getGradeYear();
    
                if (! is_null($gy))
                {
                    $year[$gy] = empty($year[$gy]) ? 1 : $year[$gy]  + 1 ;
    
                    if ($year[$gy] > 1)
                    {
                        $this->context->buildViolation('student.grades.year')
                            ->atPath('['.strval($q).']')
                            ->atPath('grade')
                            ->addViolation();
    
                        return $value;
    
                    }
                }
            }
        }
    }
    

    This results in the error being added to the field in the element of the collection as per the attach image.

    Craig

提交回复
热议问题