Imagine you have an item entity. Within this item entity, there is a method to get the prices for that item. Prices are saved in 3 different formats: EUR, USD and GBP.

The entities would look like this:

Entity WebshopItem.php

class WebshopItem
{

    /**
     * @var integer
     */
    private $id;

    /**
     * @Gedmo\Translatable
     * @var string
     */
    private $title;

    ......

    /**
     * @var \Doctrine\Common\Collections\Collection
     */
    private $prices;
}

Entity WebshopItemPrice.php

class WebshopItemPrice
{

    /**
     * @var integer
     */
    private $id;

    /**
     * @var string
     */
    private $currency;

    /**
     * @var string
     */
    private $price;

    /**
     * @var \WebshopItem
     */
    private $webshopItem;
}

Now I would like to create a form, which contains exactly 3 input fields. For that, I thought it would be best to use the money field. So I am creating the form like this:

public function buildForm(FormBuilderInterface $builder, array $options)
{
     $builder
         ->add('title')
         ....
         ->add('prices', new WebshopPricesType());
}

The webshopPricesType looks like this:

public function buildForm(FormBuilderInterface $builder, array $options)
{
     $builder
         ->add('eur', 'money', array('currency' => 'EUR', 'data_class' => 'bundlePath\Entity\WebshopItemPrice'))
         ->add('usd', 'money', array('currency' => 'USD', 'data_class' => 'bundlePath\Entity\WebshopItemPrice'))
          ->add('gbp', 'money', array('currency' => 'GBP', 'data_class' => 'bundlePath\Entity\WebshopItemPrice'));
}

3 correct fields are rendered now. I only need to fill them on edit and when saving, I have to make sure they are saved. I was thinking about using a data transformer to find the correct entity, but that's not working.

How can I make sure that all 3 fields are prefilled correctly on edit and when clicking save, the 3 prices are saved?

Or should I do it on a whole different way?

Thanks!

有帮助吗?

解决方案

I have never been too fond of DataTransformers and therefore I would not use them here, but they can be useful.

In this particular case, I would go for FormEvents and build the form dynamically, based on the data your entity contains.

WebShopItemType

public function buildForm(FormBuilderInterface $builder, array $options)
{
     $builder
         ->add('title')
         .....
         ->add('prices', 'collection', array(
            'type' => new WebshopPricesType()
         ));
}

WebshopPricesType

class WebshopPricesType extends AbstractType{
    .....

    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        // Dynamically build form fields, **after** the data has been set
        $builder->addEventListener(FormEvents::POST_SET_DATA, function(FormEvent $event) use ($builder){
            /** @var $data WebshopItemPrice **/
            $data = $event->getData(); 

            $builder->add('price', 'money', array('currency' => $data->getCurrency()));
        });
    }

    public function setDefaults(OptionsResolverInterface $resolver){
        $resolver->setDefault(array(
            'data_class' => 'bundlePath\Entity\WebshopItemPrice'
        ));
    }

    .....
}

Given that, let's glue it altogether:

public class SomeController extends Controller{
    public function insertAction(){
        $item = new WebshopItem();

        // be sure to initialize the $prices with new `ArrayCollection` 
        // in order to avoid NullPointerException
        // Also, be sure to bind WebshopItemPrice::$item
        $item
            ->addPrice(new WebshopItemPrice('EUR', 0))
            ->addPrice(new WebshopItemPrice('USD', 0))
            ->addPrice(new WebshopItemPrice('GBP', 0));

        // this is where POST_SET_DATA gets fired
        $form = $this->createForm(new WebShopItemType(), $item);

        // form is ready
    }

    public function editAction(){
        $item = ... // fetch or whatever, be sure to fetch prices as well

        // this is where POST_SET_DATA gets fired
        $form = $this->createForm(new WebShopItemType(), $item);

        // form is ready
    }
}

I have put this together in Notepad++ and I not sure if I did some typos but as far as logic is concerned - it should work ;)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top