Sylius - 覆盖 CartItemType 会破坏产品展示视图

Sylius - Overriding CartItemType breaks the Product show view

Sylius 1.0.0-dev

我正在尝试修改 CartItemType 的数量字段。

根据旧文档,我在我的 Bundle 上创建了一个新的 FormType,并从 Symfony/Bundle/CartBundle/Form/Type/CartItemType 中的原始文档扩展。

我的自定义 CartItemType 显示如下:

use Sylius\Bundle\CartBundle\Form\Type\CartItemType as BaseType;
use Symfony\Component\Form\FormBuilderInterface;


class CartItemType extends BaseType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->remove('quantity')
            ->add('quantity', 'hidden', [
                'attr' => ['min' => 1, 'max' => 1],
                'data' => '1',
                'label' => 'sylius.form.cart_item.quantity',
            ])
            ->setDataMapper($this->orderItemQuantityDataMapper);
    }
}

我希望您每个订单不能购买超过一个产品数量。

我的配置好像是这样的:

sylius_cart:
    resources:
        cart_item:
            classes:
                form:
                    default: Dinamic\Bundle\SyliusRibBundle\Form\Type\CartItemType

当我打开一些产品视图时出现此错误:

The option "product" does not exist. [...] in @SyliusShop/Product/Show/_inventory.html.twig at line 4

知道为什么会这样吗?

不要以这种方式扩展 Symfony 表单类型 - 而是扩展 Symfony\Component\Form\AbstractType,并在您的自定义类型中实现 getParent()

public function getParent()
{
    return BaseType::class;
}

这样,您的自定义类型也可以使用父项的选项,并且一切正常 rendered/initialized。

编辑:

从技术上讲,这两种方法都应该有效。但是,使用继承将 完全覆盖 父表单的行为,而使用 getParent() 会将您的自定义行为添加到父表单。

getParent() 将告诉 Symfony 首先构建该方法中定义的表单,然后将其用作您自己实现的基础。因此,当使用它时,buildForm() 方法中的 FormBuilder 将已经包含完整的父表单,准备好进行您自己的修改,configureOptions() 方法中的 OptionsResolver 将已经包含父表单的选项和默认值已定义,等等,这似乎正是您想要的(否则您对 $builder->remove() 的调用意义不大)。使用继承时,您必须注意执行父表单所做的所有您想要执行的操作,这很可能会在父表单更改时中断。

另一个区别在于 Symfony 的形式 extensions。实施 getParent() 时,应用于父表单的任何表单扩展也将应用于您的自定义表单。使用继承时,情况就不同了。

第一点很容易处理(例如,parent::buildForm() 将确保您拥有正确的字段),但第二点就没那么容易了。通常,您希望这些扩展也适用于您的自定义表单类型 - 在这种情况下,错误实际上很有可能是由未应用于您的自定义类型的表单扩展引起的。

所以基本上,尽可能使用 getParent()。仅当您想要完全覆盖行为或您明确希望表单扩展不适用于您的自定义类型时,才对表单类型使用继承。

而不是扩展 CartBundle CartItemType 使用这个扩展:

use Sylius\Bundle\CoreBundle\Form\Type\CartItemType as BaseType;

CoreBundle CartItemType class 扩展了 CartBundle CartItemType,所以如果扩展错误 class 它将破坏一切