想象一下,你有一个物品实体。在此商品实体中,有一种获取该商品价格的方法。价格以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个价格?
或者我应该以完全不同的方式做到这一点?
谢谢!
答案 0 :(得分: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
}
}
我把它放在Notepad ++中我不知道我是否做了一些拼写错误,但就逻辑问题而言 - 它应该有效;)