3

我有一个包含 2 个日期的表单:开始日期(datedebut)和结束日期(datefin)。我希望结束日期总是在开始日期之后。我怎样才能做到这一点?

我的表格类型:

class ReservationType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('datedebut',DateType::class,array(
                'widget' => 'choice',
                'years' => range(date('Y'), date('Y')+20),
            ))
            ->add('datefin',DateType::class,array(
                'widget' => 'choice',
                'years' => range(date('Y'), date('Y')+20),
            ))
            ->add('nbplaces')
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Bridge\TravelBundle\Entity\Reservation'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'Bridge_TravelBundle_Reservation';
    }
}
4

2 回答 2

2

您可以为此使用回调验证器。注入到该回调中的是ExecutionContextInterface您可以访问表单的一个,因此您可以访问其他表单参数。

这是一个例子:

use Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

// …

$builder
    ->add('start', 'datetime', 
        'constraints' => [
            new Constraints\NotBlank(),
            new Constraints\DateTime(),
        ],
    ])
    ->add('stop', 'datetime', [
        'constraints' => [
            new Constraints\NotBlank(),
            new Constraints\DateTime(),
            new Constraints\Callback(function($object, ExecutionContextInterface $context) {
                $start = $context->getRoot()->getData()['start'];
                $stop = $object;

                if (is_a($start, \DateTime::class) && is_a($stop, \DateTime::class)) {
                    if ($stop->format('U') - $start->format('U') < 0) {
                        $context
                            ->buildViolation('Stop must be after start')
                            ->addViolation();
                    }
                }
            }),
        ],
    ]);
于 2019-05-02T12:01:19.700 回答
1

通常这类任务是通过添加验证约束来检查一个字段的值是否大于另一个来解决的。按照文档中的说明实现callback验证约束:http: //symfony.com/doc/current/reference/constraints/Callback.html您还可以创建自定义类约束验证器并在其中放置验证逻辑:http ://symfony.com /doc/current/validation/custom_constraint.html

这样,每当用户尝试提交datefin小于选定值的值时,datedebut他将看到验证错误并且不会处理表单。

之后,您始终可以添加一些 javascript 代码,这些代码将在 字段中的值更改datefin后过滤字段中的可用日期。datedebut

您也可以使用动态表单修改来呈现第二个日期字段(并在服务器端过滤其可用日期),前提是提交第一个日期字段的值。看看这个:http ://symfony.com/doc/current/form/dynamic_form_modification.html

于 2017-07-08T10:25:04.310 回答