1

语境

就我而言,我有一些带有“折扣券”(折扣)的订单。折扣可以在不同的条件下使用。例如,折扣有一个过期日期,可以由有限数量的客户使用,可以专用于用户,......

每个折扣可以附加到多个订单。

在我的后台,我想在订单创建表单中添加一个“折扣”字段,其中包含可用折扣列表,但只有正确的折扣。

我做了什么

  • 具有字段 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;
    
  • 带有字段 discounts 的表单 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 请求来完成。

我尝试创建特殊类型。我的想法是有一个实体数组 Discount 并加载一个选择列表......之后,我创建了一个 dataTransformer 但它不起作用!

谢谢你的想法!

4

2 回答 2

1

例如,您可以使用$optionsfrompublic function buildForm(FormBuilderInterface $builder, array $options)传递您的userand product。使用这 2 个信息,您可以优化您的折扣列表(在您的查询中)

如果这样做,则需要将它们添加到 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,
));
于 2013-03-14T12:32:26.073 回答
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,
    ));

}
  • 创建自定义 EntityChoiceList

我的自定义类型的灵感来自 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;
}

当然,您可以尝试为 beautyfull 代码扩展 symfony 类;)。

感谢@maxwell2022 的帮助!

于 2013-03-15T14:10:41.977 回答