Reputation: 797
I followed the tutorial of Fabien Potiencier, about how to create your own Framework on top of the Symfony Components. Now i need a way. And I want to inject the Dependency Container to all my Controllers, without defining every single Controller as a Service.
In the orginal Symfony2 Framework all Controllers extends the Controller
Class located in Symfony\Bundle\FrameworkBundle\Controller\Controller.php
:
namespace Symfony\Bundle\FrameworkBundle\Controller;
class Controller extends ContainerAware
{
// ...
}
The Controller
Class extends the ControllerAware
Class, so you can do something like this in your Controller:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class MyController extends Controller
{
public function someAction()
{
$this->container->get('dependencie_xyz);
}
}
So my question is: How can I accomplish the same in my Framework?
Upvotes: 3
Views: 5305
Reputation: 61
If you are not implementing any interface on controller you can add the this way and it will work. This is a small modification to c4pone implementation.
/**
* Description of ContainerAwareControllerResolver
*
* @author sbc
*/
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
class ContainerAwareControllerResolver extends ControllerResolver {
private $container;
public function __construct(LoggerInterface $logger = null, ContainerInterface $container = null) {
parent::__construct($logger);
$this->container = $container;
}
protected function instantiateController($class) {
$new_class = new $class();
$new_class->setContainer($this->container);
return $new_class;
}
Upvotes: 0
Reputation: 1775
It is too simply. The next code will help you
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
use Symfony\Component\DependencyInjection\ContainerAware as ContainerAware;
class TestService extends ContainerAware
{
public function __construct(Container $container) {
// in your example from official doc 'dependencie_xyz' is a name of service
$this->setContainer($container); // call parent setContainer() method, for identifying container variable, from now you can access to ServiceContainer using $this->container variable
$test_param = $this->container->getParameter('test_param'); // get test_param from config.yml
}
}
in service.yml
write smthing like this
services:
test_service:
class: Symfony\Bundle\FrameworkBundle\TestService
arguments: ['@service_container']
and post service container as argument
Upvotes: 0
Reputation: 797
It took me a while, but i finally figured out how the Symfony2 Framework does it. In the SymfonyFrameworkBundle is a custom ControllerResolver, which call the setContainer Method on the resolved controller. The controller has to be a instance of the ContainerAwareInterface.
Simplified version:
class ContainerAwareControllerResolver extends ControllerResolver
{
private $container;
public __construct(ContainerInterface $container)
{
$this->container = $container;
parent::__construct();
}
public function getController(Request $request)
{
$controller = parent::getController($request);
if($controller instanceof ContainerAware ){
$controller->setContainer($this->container);
}
}
}
Source:
Upvotes: 3
Reputation: 41934
The Controller Class extends the ControllerAware Class, so you can do something like this in your Controller:
Well, this is not true. If we take a look at the signature of the ContainerAware
class, we see that this added a setContainer
method so we can set the container. Symfony2 has created the Controller::get
method to make some live easier.
We can see how they do it in the source code:
/**
* Gets a service by id.
*
* @param string $id The service id
*
* @return object The service
*/
public function get($id)
{
return $this->container->get($id);
}
You can put this in your own Controller
class and let all your controllers extend that controller class.
Upvotes: -1