【问题标题】:Extend Doctrine2 form EntityType从 EntityType 扩展 Doctrine2
【发布时间】:2017-01-23 13:23:11
【问题描述】:

我正在寻找一种扩展 Symfony 2 EntityType 的方法

Symfony\Bridge\Doctrine\Form\Type\EntityType

作为扩展这个类型的新类型,而不是创建FormTypeExtension - 我无法弄清楚。有谁知道这样做的正确方法吗?

我尝试过以这种方式简单地扩展它:

class NestedEntityType extends EntityType {

    public function getName() {
        return $this->getBlockPrefix();
    }

    public function getBlockPrefix() {
        return 'nested_entity';
    }
}

然后在奏鸣曲管理课上我有:

protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper->add('types', NestedEntityType::class, [
        'label' => false,
        'multiple' => true,
        'expanded' => true,
        'by_reference' => false
    ]);
}

但不幸的是它会导致致命错误:

可捕获的致命错误:参数 1 传递给 Symfony\Bridge\Doctrine\Form\Type\DoctrineType::__construct() 必须 实现接口 Doctrine\Common\Persistence\ManagerRegistry,无 给定的,调用的

我需要保留EntityType 的全部功能,但有一个例外 - 它的呈现方式。这就是为什么我需要扩展这个类型(我在其他领域使用它,所以我不能只为它修改模板!)。

我正在使用 Symfony 2.8(仅作记录)。

【问题讨论】:

    标签: php symfony doctrine-orm sonata-admin symfony2-forms


    【解决方案1】:

    因此,如果您需要为不同的实体创建可重用的解决方案,在这种情况下您不需要 configureOptions。

    你需要在你的代码中创建一个 elementType 像

    $this->createForm(NestedEntityType::class, null, ['class' => YourEntity::class]);

    在这种情况下,您需要将嵌套的类实体的名称作为选项传递。

    【讨论】:

    • Sonata / Symfony 不可能像 EntityType 那样自动执行此操作?好吧,我想我可以忍受,如果没有其他办法:)
    • 我认为这是可能的。毕竟是 Symfony。但是你需要深入挖掘代码并首先完全理解它是如何与 EntityType 一起工作的
    • 这就是我的假设,好吧,现在我可以接受class 选项。感谢您的支持!
    【解决方案2】:

    如果你去EntityType,你会看到它正在扩展DoctrineType,并且需要构造函数中的依赖项 -

    public function __construct(ManagerRegistry $registry, PropertyAccessorInterface $propertyAccessor = null)
    {
        $this->registry = $registry;
        $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
    }
    

    所以,您的类 NestedEntityType 使用相同的构造函数并需要相同的依赖项。

    其实你需要的是

    class NestedEntityType extends AbstractType {
    
        public function getParent() {
            return EntityType::class;
        } 
    
        public function getName() {
            return $this->getBlockPrefix();
        } 
    
        public function getBlockPrefix() {
            return 'nested_entity';
        }
    
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'class' => YourEntity::class
            ]);
        }
    }
    

    UPD:当然你需要配置选项,根据EntityType doc。请参阅我添加到代码中的方法。

    【讨论】:

    • 您在AbstractType 中有错字!也谢谢你,它确实推动了我前进,不幸的是我现在得到:The required option "class" is missing.,因此它不是 EntityType 的 1:1 扩展,因为我仍然需要一些额外的东西来使它工作;> 我采取了一种方法将参数传递给构造函数,但不幸的是我找不到任何匹配的服务作为参数传递,你有没有机会知道我应该在服务定义中添加什么才能使其工作?
    • 当然,您需要选项class。查看更新的答案。
    • 啊,对 :> 我相信它是由 Sonata 自动传递给 EntityType 的?
    • 我可以在那里传递一个特征吗?我想在这里使用 Gedmo NestedTree。
    • 由 Symfony 准确地说。
    【解决方案3】:

    你不应该直接扩展它,而是使用parent选项

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return EntityType::class;
    }
    

    类似

    class NestedEntityType extends AbstractType 
    {
    
        public function getName() 
        {
            return $this->getBlockPrefix();
        }
    
        public function getBlockPrefix() 
        {
            return 'nested_entity';
        }
    
        /**
         * {@inheritdoc}
         */
        public function getParent()
        {
            return EntityType::class;
        }
    }
    

    这样,如果你扩展的 FormType 有一些东西被注入(或设置)到构造函数中,你不需要关心,因为 symfony 会为你做。

    【讨论】:

    • The required option "class" is missing. - 我只能假设这与奏鸣曲有关,而不是 Symfony2 本身?
    • @user1970395 它与您使用NestedEntityType 的表单有关。解决方案:作为一个选项,您需要传递您正在使用该表单类型的实体类。
    • 感谢您的帮助!我很想将两个答案都标记为已接受,但 Dmitry 更深入地涵盖了这个问题,所以我会标记他的答案! :) 希望你不介意。
    • @user1970395 标记您认为最能帮助社区的人:我们是来帮助和被帮助的,而不是为了获得声誉;)
    猜你喜欢
    • 2023-03-28
    • 2012-06-12
    • 2012-09-29
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 2015-07-22
    • 1970-01-01
    相关资源
    最近更新 更多