上下文
在我的情况下,我有一些订单带有“折扣优惠券”(折扣)。可以在不同条件下使用折扣。例如,折扣有过期日期,可供有限数量的客户使用,可专用于用户,......
每个折扣都可以附加到多个订单。
在我的后台,我想添加订单创建一个字段“折扣”,其中包含折扣列表,但只有正确的折扣。
我做了什么
具有字段manyToMany
的实体“订单”/**
* @ORM\ManyToMany(targetEntity="PATH\MyBundle\Entity\Discount", inversedBy="orders")
* @ORM\JoinTable(name="shop_discounts_orders",
* joinColumns={@ORM\JoinColumn(name="order_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="discount_id", referencedColumnName="id")}
* )
*/
private $discounts;
实体使用字段manyToMany“折扣”
/**
* @ORM\ManyToMany(targetEntity="PATH\MyBundle\Entity\Order", mappedBy="discounts")
*/
private $orders;
带有字段折扣的表单OrderType
$builder->add('discounts', 'entity',
array( 'label' => 'Discount vouchers',
'required' => false,
'expanded' => true,
'class' => 'PATH\MyBundle\Entity\Discount',
'property' => 'title',
'multiple' => true,
'query_builder' => function(EntityRepository $er) use ($params) {
return $er->getQuerySelectType($params);
},
));
使用此解决方案,我可以在我的实体存储库中返回由我的请求定义的特定折扣。例如,它适用于过期的日期条件。
我想要什么
我想在复选框列表中过滤结果。实际上,我希望将折扣限制用于专用用户,限制产品列表或限制使用次数......而这些条件不能通过简单的sql请求来完成。
我尝试创建特殊类型。我的想法是有一个实体数组折扣并加载一个选择列表......之后,我创建了一个dataTransformer但它不起作用!
感谢你的想法!
答案 0 :(得分:1)
您可以使用$options
中的public function buildForm(FormBuilderInterface $builder, array $options)
来传递您的user
和product
。通过这两个信息,您可以优化折扣列表(在您的查询中)
如果您这样做,则需要在setDefaultValue
中添加它们public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'user_discount' => null,
'product_discount' => null,
));
}
并在您的控制器中:
$form = $this->formFactory->create(new YourFormType(), $entity, array(
'user_discount' => $this->getUser(),
'product_discount' => $product,
));
答案 1 :(得分:0)
如果有人和我有同样的问题,我找到了解决方案并解释了它。
我的自定义类型受Symfony \ Bridge \ Doctrine \ Form \ Type \ DoctrineType
的启发class DiscountOrderType extends AbstractType
{
// overide choiceList callback
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$choiceListCache =& $this->choiceListCache;
$type = $this;
$choiceList = function (Options $options) use (&$choiceListCache, &$time, $container) {
[[ Copy paste same as Doctrine type ]]
// Create your own choiceList class (EntityChoiceList)
if (!isset($choiceListCache[$hash])) {
$choiceListCache[$hash] = new DiscountChoiceList(
$options['em'],
$options['class'],
$options['property'],
$options['loader'],
$options['choices'],
$options['group_by']
);
// If you want add container
$choiceListCache[$hash]->setContainer($container);
}
return $choiceListCache[$hash];
};
$resolver->setDefaults(array(
'choice_list' => $choiceList,
));
}
我的自定义类型的灵感来自Symfony \ Bridge \ Doctrine \ Form \ ChoiceList \ EntityChoiceList
class EntityChoiceList extends ObjectChoiceList
{
protected function load()
{
if ($this->entityLoader) {
$entities = $this->entityLoader->getEntities();
} else {
$entities = $this->em->getRepository($this->class)->findAll();
}
// You have access to the entities in the choice list
// Add your custom code here to manipulate the choice list
// you can do some check not properly possible with sql request (http requests on each result, ...) before add it in choice list
// you can add some custom cache rules, ...
// if you use gedmon and want apply a "join" with translate table, you can add $query->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER, 'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'); before playing request...
// Possibilities are infinite
// FOR INSTANCE : you already want unset first entity of the result
if (isset($entities[0])) {
unset($entities[0]);
}
// END OF CUSTOM CODE
try {
// The second parameter $labels is ignored by ObjectChoiceList
// The third parameter $preferredChoices is currently not supported
parent::initialize($entities, array(), array());
} catch (StringCastException $e) {
throw new StringCastException(str_replace('argument $labelPath', 'option "property"', $e->getMessage()), null, $e);
}
$this->loaded = true;
}
当然你可以尝试扩展symfony类以获得美丽的代码;)。
感谢@ maxwell2022的帮助!