pzaj
pzaj

Reputation: 1092

Extend Doctrine2 form EntityType

I'm looking for a way to extend Symfony 2 EntityType

Symfony\Bridge\Doctrine\Form\Type\EntityType

as in a new type extending this one, not creating a FormTypeExtension - and I can't figure it out. Does anyone know any proper way to do that?

I've tried simply extending it that way:

class NestedEntityType extends EntityType {

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

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

and then in sonata admin class I have:

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

but unfortunately it causes Fatal Error:

Catchable Fatal Error: Argument 1 passed to Symfony\Bridge\Doctrine\Form\Type\DoctrineType::__construct() must implement interface Doctrine\Common\Persistence\ManagerRegistry, none given, called in

I need to keep the whole functionality of EntityType, with one exception - the way it's presented. That's why I need to extend this type (I use it in other fields, so I can't just modify the template for it!).

I'm using Symfony 2.8 (just for the record).

Upvotes: 2

Views: 1484

Answers (3)

Dmitry Malyshenko
Dmitry Malyshenko

Reputation: 3051

So, if you need a create a reusable solution, for different Entities, you don't need a configureOptions in this case.

You need to create an elementType in you code like

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

And in this case, you will need to pass as an option a name of class Entity which is nested.

Upvotes: 1

Dmitry Malyshenko
Dmitry Malyshenko

Reputation: 3051

If you would go to EntityType, you'll see it's extending DoctrineType and needs dependencies in constructor -

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

So, your class NestedEntityType uses the same constructor and needs the same dependencies.

Actually, what you need is

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: Of course you need configure options, according to EntityType doc. See method I've added to code.

Upvotes: 1

DonCallisto
DonCallisto

Reputation: 29922

You should not extend it directly but use parent option

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

So something like

class NestedEntityType extends AbstractType 
{

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

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

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

That way if FormType you're extending from has something in injected (or setted) into constructor, you don't need to care as symfony will do it for you.

Upvotes: 9

Related Questions