Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inject Symfony EntityManager into Form Type via Services

I need to modify some fields in my form (label and class), based on whether the entity is the latest published version or not. So I need to be able to inject the entity manager into my formType so that in an event listener I can compare the current version with the published version of the entity. But I can't even get the entityManager into the __construct() to begin with. Maybe there is a better way of achieving my big goal as well (e.g. modify the form in the twig template), but I NEED to understand how to do this basic dependency inject as well.

I thought that if I declare it in my service (like the documentation describes for basic Service Container and specifically Constructor Injection methods), it will be available as an argument in my construct. But when I do this, I get the error:

Catchable fatal error: Argument 1 passed to Gutensite\CmsBundle\Form\Type\ViewType::__construct() must be an instance of Doctrine\ORM\EntityManager, none given, called in /var/www/core/cms/src/Gutensite/ArticleBundle/Controller/AdminEditController.php on line 222 and defined in /var/www/core/cms/src/Gutensite/CmsBundle/Form/Type/ViewType.php on line 15

Here are the snippets from my code:

Gutensite/CmsBundle/Resources/config/service.yml

gutensite_cms.form.type.view:
    class: Gutensite\CmsBundle\Form\Type\ViewType
    arguments: [ "@doctrine.orm.entity_manager" ]

Gutensite/CmsBundle/Form/Type/ViewType.php

namespace Gutensite\CmsBundle\Form\Type;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\AbstractType;

class ViewType extends AbstractType
{

    private $em;

    public function __construct(EntityManager $entityManager) {
        $this->em = $entityManager;
    }
}

Gutensite/ArticleBundle/Controller/AdminEditController.php

// Get the View Entity
$em = $this->getDoctrine()->getManager();
$viewRepo = $em->getRepository("GutensiteCmsBundle:View\View");
$view = $viewRepo->find($request->query->get('id'));

// Create the generic form for editing any View, using the view entity constructed
$form = $this->createForm(new ViewType(), $view);

NOTE:

I am using two entity managers, so my config.yml looks something like this. I don't know if that makes any difference in what I inject, i.e. can I inject @doctrine.orm.entity_manager or am I supposed to inject @doctrine.orm.default_entity_manager or something? I've tried all sorts of options and none work.

# Doctrine Configuration
doctrine:
    dbal:
        default_connection: cms
        connections:
            cms:
                driver:   "%db.cms.driver%"
                host:     "%db.cms.host%"
                port:     "%db.cms.port%"
                dbname:   "%db.cms.name%"
                user:     "%db.cms.user%"
                password: "%db.cms.password%"
                charset:  "%db.cms.charset%"
            billing:
                driver:   "%db.billing.driver%"
                host:     "%db.billing.host%"
                port:     "%db.billing.port%"
                dbname:   "%db.billing.name%"
                user:     "%db.billing.user%"
                password: "%db.billing.password%"
                charset:  "%db.billing.charset%"
    orm:
        default_entity_manager: cms
        entity_managers:
            cms:
                connection: cms
                mappings:
                    GutensiteCmsBundle: ~
                    GutensiteArticleBundle: ~
            billing:
                connection: billing
                mappings:
                    GutensiteBillingBundle: ~
        auto_generate_proxy_classes: "%kernel.debug%"

Referenced Already:

  • Symfony 2 EntityManager injection in service
  • Symfony2 inject EntityMananager in FormType

Solution:

I didn't need to define ViewType as a service, I just needed to pass in the entity manager via new viewType($em) when I created the new ViewType form:

Gutensite/ArticleBundle/Controller/AdminEditController.php

// Get the View Entity
$em = $this->getDoctrine()->getManager();
$viewRepo = $em->getRepository("GutensiteCmsBundle:View\View");
$view = $viewRepo->find($request->query->get('id'));

// Create the generic form for editing any View, using the view entity constructed
$form = $this->createForm(new ViewType($em), $view);
like image 598
Chadwick Meyer Avatar asked Jan 10 '23 04:01

Chadwick Meyer


2 Answers

You got that error because you`re creating form type like this:

$form = $this->createForm(new ViewType(), $view);

You create new object ViewType without any arguments and it needs to be called with EntityManager. You can simply pass entity manager from controller, like this:

$em = $this->get('doctrine.orm.entity_manager'); // or doctrine.orm.billing_entity_manager
$form = $this->createForm(new ViewType($em), $view);

In this case you don't even need to define this form type as a service.

Use of doctrine.orm.entity_manager or doctrine.orm.billing_entity_manager depends on what you need to fetch inside ViewType - (from witch database).

UPDATE:

Define form type as a service.

Add this two services to your configuration (services.yml):

services
    gutensite_cms.form.view:
        factory_method: createNamed
        factory_service: form.factory
        class: Symfony\Component\Form\Form
        arguments:
            - view_form                        # name of the form
            - view                             # alias of the form type
            - null                             # data to bind, this is where your entity could go if you have that defined as a service
            - { validation_groups: [Default] } # validation groups

    gutensite_cms.form.type.view:
        class: Gutensite\CmsBundle\Form\Type\ViewType
        arguments: [ "@doctrine.orm.entity_manager" ]
        tags:
            - { name: form.type, alias: view }

Then you can create new form by executing this inside your controller (or whatever has container) without manualy passing any arguments (they will be injected automaticly):

public function newAction()
{
    $view = ...;
    $form = $this->get( 'gutensite_cms.form.view' );

    // set initial form data if needed
    $form->setData( $view );
}
like image 58
4 revs, 2 users 93% Avatar answered Jan 18 '23 00:01

4 revs, 2 users 93%


You created a new ViewType without passing the EntityManager. Get the form type from the dic with

$form = $this->createForm($this->get('gutensite_cms.form.type.view'), $view);

or create a new object with the entity manager as an argument

$form = $this->createForm(new ViewType($this->getDoctrine()->getManager()), $view);
like image 25
denga Avatar answered Jan 17 '23 22:01

denga