3

1 つのフォーム (たとえば、日付と時刻) の 2 つの分離されたフィールド (分離する必要があります) を 1 つのエンティティ プロパティ datetime に結合して、フォームの投稿後に永続化することはどのように可能ですか?

より良い方法は何ですか?データトランスフォーマー? フォーム イベント ? フォームモデル? 永続化する前にすべてのエンティティ プロパティを手動で設定しますか?

実在物:

<?php namespace Acme\DemoBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="event")
 */
class EventEntity
{

    /**
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    // ...

    /**
     * @ORM\Column(name="date_time", type="datetime", nullable=false)
     */
    protected $datetime;

    public function getId()
    {
        return $this->id;
    }

    // ...

    public function getDateTime()
    {
        return $this->datetime;
    }

    public function setDateTime(\DateTime $datetime)
    {
        $this->datetime = $datetime;
    }

}

フォームタイプ:

<?php namespace Acme\DemoBundle\Form\Type;

use JMS\DiExtraBundle\Annotation as DI;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class EventType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            // ...
            ->add('date', 'date', [
                    'required' => true,
                    'widget'   => 'single_text',
                    'format'   => 'dd.MM.yyyy'
                ]
            )
            ->add('time', 'time', [
                    'required' => false,
                    'widget'   => 'single_text'
                ]
            );
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\DemoBundle\Entity\EventEntity' //Acme\DemoBundle\Form\Model\EventModel ?
        ));
    }

    public function getName()
    {
        return 'event';
    }

}
4

3 に答える 3

7

日時ウィジェットを個別に日時型に設定すると、それらは個別にレンダリングされますが、1 つのフィールドとして検証されます。

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('datetime', 'datetime', array(
            'date_widget' => 'single_text',
            'time_widget' => 'single_text',
            'date_format' => 'dd.MM.yyyy',
        ));
}
于 2013-07-01T20:55:19.793 に答える
5

これは最も単純なものであるため、Pazis ソリューションを使用することをお勧めします。しかし、それは DataTransformer にとっても完璧な仕事です。

class MyDataTransformer implements DataTransformerInterface
{
  public function transform($value)
  {
    if (null === $value)
      return;

    if ($value instanceof \DateTime)
      return array(
        'date' => $value->format('d.m.Y'),
        'time' => $value->format('H:i:s')
      );

    return null;
  }

  public function reverseTransform($value)
  {
    if (null === $value)
      return null;

    if (is_array($value) && array_key_exists('date', $value) && array_key_exists('time', $value))
      return new \DateTime($value['date'] . ' ' . $value['time']);

    return null; 
  }
}

これには、エンティティ内のすべての値をこのトランスフォーマーでマップする必要があるという欠点があります。確かに、したくないことです。しかし、小さなフォーム トリックを使用すると、これを回避できます。したがって、フォームにサブフォームを追加します。これには、日付と時刻のフィールドと、追加された Transformer が含まれます。DateTime オブジェクトをこのサブフォームにマップ ("property_path"-option) するか、単に「正しく」名前を付ける必要があります。これにより、フォーム フレームワークが名前でマップできるようになります。

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add(
        $builder->create('datetime', 'form')
                ->add('date', 'date', $optionsForDate)
                ->add('time', 'time', $optionsForTime)
                ->addViewTransformer(new MyDataTransformer())
    );
}

コードは完全に実行されていない可能性がありますが、1 つのエンティティ プロパティを 2 つ (またはそれ以上) のフォーム フィールドに分割する背後にあるアイデアが明確であることを願っています。

于 2013-07-02T08:39:35.420 に答える
1

ヘヘ、それは良い質問です。

私は、最も簡単で、最も一般的で、再利用可能なソリューションを選択します。フォーム マッピングのためだけにモデルにメソッドを実装するつもりはありませんが、それが理にかなっている場合は、単にモデル api を使用しないのはなぜですか?

<?php

class EventEntity
{
// assume $this->datetime is initialized and instance of DateTime

public function setDate(\DateTime $date)
{
    // i don't know if this works!
    $this->datetime->add($this->datetime->diff($date));
}


public function setTime(\DateTime $date)
{
    $this->datetime->add($this->datetime->diff($date));
}
}
于 2013-07-01T20:54:10.380 に答える