DataTransformer - split DateTime into two fields

后端 未结 1 1239
名媛妹妹
名媛妹妹 2021-01-14 08:59

I recently build a DataTransformer that will accept a variety of different date formats in the end (like 12/12/2012 or 12.12.2012 or 2012-12-12).

相关标签:
1条回答
  • 2021-01-14 09:38

    I'm assuming you are using Symfony 2.0. I've read that form component has changed somewhat in 2.1.

    I had a similar problem - I wanted to have a datetime field that uses separate widgets for date and time (hour) input.

    First of all, you have to create a separate form type for this field (which actually is a form in itself).

    My code looks similar to this (altered for this example):

    class MyDateTimeType extends AbstractType
    {
        public function buildForm(FormBuilder $builder, array $options)
        {
            $builder
            ->add('date', 'date', array(
                'label'  => 'label.form.date',
                'input'  => 'datetime',
                'widget' => 'single_text',
                'format' => 'yyyy-MM-dd',
                'error_bubbling' => true
            ))
            ->add('time', 'time', array(
                'label'  => 'label.form.time',
                'input'  => 'datetime',
                'widget' => 'choice',
                'error_bubbling' => true
            ));
    
            $builder->appendClientTransformer(new DateTimeToDateTimeArrayTransformer());
        }
    
        public function getDefaultOptions(array $options)
        {
            return array(
                'label' => 'label.form.date',
                'error_bubbling' => false
            );
        }
    
        public function getParent(array $options)
        {
            return 'form';
        }
    
        public function getName()
        {
            return 'my_datetime';
        }
    }
    

    As you can see it is a form (don't let it confuse you) but we will use it as a single logical field. That's where the data transformer comes in. It has to split a single DateTime instance into date and time to obtain data for the two subfields when displaying the form and vice-versa when the form is submitted.

    The error_bubbling settings ensure that the errors generated by subfields attach to our new subfield and don't propagate to the top-level form, but you may have diferrent goal.

    My data transformer looks like this:

    class DateTimeToDateTimeArrayTransformer implements DataTransformerInterface
    {
        public function transform($datetime)
        {
            if(null !== $datetime)
            {
                $date = clone $datetime;
                $date->setTime(12, 0, 0);
    
                $time = clone $datetime;
                $time->setDate(1970, 1, 1);
            }
            else
            {
                $date = null;
                $time = null;
            }
    
            $result = array(
                'date' => $date,
                'time' => $time
            );
    
            return $result;
        }
    
        public function reverseTransform($array)
        {
            $date = $array['date'];
            $time = $array['time'];
    
            if(null == $date || null == $time)
                return null;
    
            $date->setTime($time->format('G'), $time->format('i'));
    
            return $date;
        }
    }
    

    Finally you can use it like that:

    $builder->add('startDate', 'my_datetime', array(
           'label' => 'label.form.date'
    ));
    

    You have to register it as a service to use it by alias, otherwise instantiate it directly (new MyDateTimeType()).

    This may not be the prettiest solution but so is the form component in Symfony 2.0.

    0 讨论(0)
提交回复
热议问题