Ограничение на значение объекта в форме Symfony - PullRequest
0 голосов
/ 11 сентября 2018

Я довольно новичок в Symfony, и я начал копаться в формах Symfony.Как описано здесь https://webmozart.io/blog/2015/09/09/value-objects-in-symfony-forms/ Я использую объекты значений в моей подчиненной форме.Конструктор объекта value может вызвать исключение, если указаны недопустимые значения.Поэтому, когда я помещаю недопустимое значение в свое поле, я получаю ужасное исключение из VO, поэтому я хочу подключить к нему ограничение Validator, но функция validate () уже получает объект Value ... Есть мысли по этому вопросу?

    class AddressType extends AbstractType
    {     
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            /....
           $builder->add('latitude', LatitudeType::class, [
                'label'       => false,
                'constraints' => [new Valid()],
            ]);
       }

Тип широты

 class LatitudeType extends AbstractType implements DataMapperInterface
{
    const INPUT_NAME = 'latitude';

    /**
     * @param FormBuilderInterface $builder
     * @param array                $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add(self::INPUT_NAME, TextType::class, [
            'label'       => 'FORM.LATITUDE',
            'attr'        => [
                'placeholder' => 'PLACEHOLDER.LATITUDE',
            ],
            'required'    => false,
            'constraints' => [new LatitudeValidator()],
        ]);

        $builder->setDataMapper($this);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Latitude::class,
            'empty_data' => null,
            'error_bubbling' => true
        ]);
    }

    /**
     * @param Latitude                     $data
     * @param FormInterface[]|\Traversable $forms
     */
    public function mapDataToForms($data, $forms)
    {
        $forms = iterator_to_array($forms);
        $forms[self::INPUT_NAME]->setData($data);
    }

    /**
     * @param FormInterface[]|\Traversable $forms
     * @param mixed                        $data
     */
    public function mapFormsToData($forms, &$data)
    {
        $forms = iterator_to_array($forms);
        if ($forms[self::INPUT_NAME]->getData()) {
            $data = new Latitude((float)$forms[self::INPUT_NAME]->getData());
        }
    }

Этот метод проверки уже получает созданный VO

class LatitudeValidator extends ConstraintValidator
{
    /**
     * {@inheritdoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

Но я хочу иметь возможность сделать что-то вроде

 try {
        new \ValueObject\Latitude((float)$value);
    } catch (\InvalidArgumentException $e) {
        $this->context->buildViolation($e->getMessage())
            ->addViolation();
    }

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

У вас есть разные методы для использования формы с объектами значения, но после многих неприятностей со мной я решил это прекратить. Symfony должен создать вам Value Object, даже если ваш VO недействителен. Вы привели пример о недопустимом состоянии, но у вас есть и другой пример, когда форма не подходит для вашего домена. Например, когда вы не заполнили поля для заполнения необходимых свойств в ваших VO.

Формы Symfony могут быть сложными, и использование виртуальных организаций внутри них может привести к большей сложности, тогда как формы должны быть связаны с интерфейсом, а не всегда с объектами домена.

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

С помощью команды вы можете просто представить действие с помощью формы. Форма может иметь валидаторы, связанные с ВО или непосредственно с формой.

С помощью командной шины вы можете создать объект Value в действительном состоянии и создавать исключения во втором слое, когда вы забудете сценарий использования.

Этот подход является более надежным и позволяет избежать многих неприятностей с моей точки зрения.

0 голосов
/ 11 сентября 2018

Лучшее, чего вы достигнете - это принять любое значение в ValueObject и затем выполнить его проверку.Таким образом, вы не обязаны обрабатывать исключения из-за недопустимых типов, передаваемых через конструктор.Кроме того, помните, что создание или «установка значений» базового объекта выполняется структурой до проверки (в противном случае вам никогда не придется использовать VO), поэтому вы должны использовать это и позволить компоненту Form выполнить его.работа (как вы сделали с трансформаторами).Затем вы можете выполнить любой вид проверки базового объекта.

...