Question

I'm having a problem with passing the entity manager between two layers of controllers.

The system I'm building has the following structure:

2 Bundles:

Core Bundle (let's call it Backend Controller)

This is the bundle that contains all the Models (entities) and business rules/logic.

API Bundle (call it Frontend controller)

Is responsible for checking the permissions of passed in api keys and communicating with the Core bundle to get the info.

Here's an example with the User controllers and entities:

UserController.php in APIBundle:

<?php

namespace Acme\Bundle\APIBundle\Controller;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;

use Acme\Bundle\CoreBundle\Controller\UserController as User;


use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class UserController extends BaseController implements AuthenticatedController
{

    public function readAction(Request $request) {

        $user = new User($this->getDoctrine()->getManager());

        $user->load(2);

        return $this->response($user);
    }
}

UserController.php in CoreBundle:

<?php

namespace Acme\Bundle\CoreBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Response;

use Acme\Bundle\CoreBundle\Entity\User;

class UserController extends BaseController
{

    function __construct($em) {
        parent::__construct($em);
        $this->entity = new User();
    }

    /**
     * Get userId
     *
     * @return integer 
     */
    public function getUserId()
    {
        return $this->entity->userId;
    }

    /**
     * Set firstName
     *
     * @param string $firstName
     * @return User
     */
    public function setFirstName($firstName)
    {
        $this->entity->firstName = $firstName;

        return $this;
    }

    // ...
    public function load($id) {

    if (!$this->entity instanceof \Acme\Bundle\CoreBundle\Entity\BaseEntity) {
        throw new \Exception('invalid entity argument');
    }

    $this->entity = $this->em->getRepository('AcmeCoreBundle:User')->find($id);
    }
}

Please, tell me if I'm doing this right. It seems strange to pass the entity manager between the controllers every time.

Maybe there's a better way of doing that?

Does the idea between the separation of the bundles make sense?

Thank you, every idea is greatly appreciated.

Was it helpful?

Solution

If CoreBundle UserController is never accessed through HTTP nor do its methods return instances of Symfony\Component\HttpFoundation\Response then it's not really a controller.

You should better define it as a service, as in CoreBundle\Service\User, and inject the EntityManager through the DI container.

sevices.yml

  corebundle.userservice:
    class:  Acme\CoreBundle\Service\User
    arguments: [@doctrine.orm.entity_manager]

It will then be available from Acme\Bundle\APIBundle\Controller\UserController with the following:

$user = $this->get('corebundle.userservice');

Of course, you can also define Acme\Bundle\APIBundle\Controller\UserController as a service on its own, then inject 'corebundle.userservice', for convenience.

I suggest you read the Symfony docs on Dependency Injection.

OTHER TIPS

Search to get entity manager in Entity class is a wrong way !

In CoreBundle, you use the UserController.php same as an Entity class.

Read docs to understand how to properly use repository in symfony.

In UserController of APIBundle you must call a custom repository function. This repository is declare in your entity.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top