【问题标题】:Symfony: Multiple money fields in one formSymfony:一种形式的多个货币字段
【发布时间】:2014-03-17 20:14:11
【问题描述】:

想象你有一个物品实体。在这个项目实体中,有一种方法可以获取该项目的价格。价格以 3 种不同的格式保存:欧元、美元和英镑。

实体看起来像这样:

实体 WebshopItem.php

class WebshopItem
{

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

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

    ......

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

实体 WebshopItemPrice.php

class WebshopItemPrice
{

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

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

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

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

现在我想创建一个表单,其中正好包含 3 个输入字段。为此,我认为最好使用货币字段。所以我正在创建这样的表单:

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

webshopPricesType 如下所示:

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 个正确的字段。我只需要在编辑时填写它们,保存时,我必须确保它们被保存。我正在考虑使用数据转换器来查找正确的实体,但这不起作用。

如何确保在编辑时正确预填所有 3 个字段,并在单击保存时保存 3 个价格?

或者我应该以完全不同的方式来做吗?

谢谢!

【问题讨论】:

    标签: php forms symfony currency


    【解决方案1】:

    我从来没有太喜欢DataTransformers,因此我不会在这里使用它们,但它们会很有用。

    在这种特殊情况下,我会选择 FormEvents 并根据您的实体包含的数据动态构建表单。

    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'
            ));
        }
    
        .....
    }
    

    鉴于此,让我们将其完全粘合:

    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
        }
    }
    

    我已经把它放在记事本++中,我不确定我是否有一些错别字,但就逻辑而言 - 它应该可以工作;)

    【讨论】:

    • 有趣的方法。我稍后会尝试让您知道它是否有效,如果有效,请将您的答案标记为已接受:)
    • 您的解决方案似乎很接近,但并不完全。我现在也在挖掘自己:表单的视图数据应该是标量、数组或\ArrayAccess 的实例类型,但它是Entity\WebshopItemPrice 类的实例。您可以通过将“data_class”选项设置为“Entity\WebshopItemPrice”或添加将 Entity\WebshopItemPrice 类的实例转换为标量、数组或 \ArrayAccess 的实例的视图转换器来避免此错误。
    • 啊,太好了! :) 很高兴我能帮上忙! :)
    猜你喜欢
    • 2015-10-24
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 2018-03-13
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2013-04-23
    相关资源
    最近更新 更多