Reputation: 1196
I have the following controller:
namespace Acme\CompanyBundle\Controller;
use Symfony\Component\DependencyInjection\Container;
/**
* Company controller.
*
*/
class CompanyController extends Controller
{
protected $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function getData()
{
$userObj = $this->container->get('security.context')->getToken()->getUser();
}
}
In my services.yml
file, I have injected Container
class:
parameters:
acme.controller.company.class: Acme\ContainerBundle\Controller\CompanyController
services:
acme.controller.company:
class: %acme.controller.company.class%
arguments: [@service_container]
When loading this controller, I get following error:
Catchable Fatal Error: Argument 1 passed to Acme\CompanyBundle\Controller\CompanyController::__construct() must be an instance of Symfony\Component\DependencyInjection\Container, none given, called in C:\wamp\www\symfony\app\cache\dev\classes.php on line 2785 and defined in C:\wamp\www\symfony\src\Acme\CompanyBundle\Controller\CompanyController.php line ...
As you could see, this is a simple injection of Container
object into a controller but throws nice errors. What is the problem here?
Similar issue is posted in another SO thread here.
Upvotes: 0
Views: 863
Reputation: 533
Never and never inject the container inside something (services, controller or whatever) Instead try to inject the securityContext or access it through the helper method of symfony controller as suggested above.
The token it's not an object just because probably the route of the controller it's not under a firewall
Upvotes: 1
Reputation: 48865
By default, routes look something like this:
cerad_player_wanabe_list:
pattern: /player-request/list
defaults:
_controller: CeradPlayerWanabeBundle:Player/PlayerList:list
The Symfony\Component\HttpKernel\HttpKernel::handle($request) method pulls the _controller attribute from the request object. If the attribute has two colons in it then it translates the attribute into a class name and creates an instance using the new operator. If the instance implements the ContainerAwareInterface then the container is injected into the controller instance. The controller service you defined is not used. Hence the error about no argument being passed to the constructor.
On the other hand, if _controller has only one colon then the controller is pulled as a service from the container. There is no checking for the ContainerAwareInterface. It's up to you to inject the dependencies via your service definition.
This is all documented in: http://symfony.com/doc/current/cookbook/controller/service.html
So for this particular question, your route should be something like:
cerad_player_wanabe_list:
pattern: /player-request/list
defaults:
_controller: acme.controller.company:action
This does raise the question of why you are trying to define the controller as a service. The default approach already does exactly what you want so you are not gaining anything.
The rationale for defining services as containers is that you can control exactly what dependencies the controller uses. Makes the controller easier to understand and test.
Injecting the complete container pretty much destroys the value of defining the controller as a service.
Upvotes: 1
Reputation: 1480
You don't need to inject the container in controllers as long as they extend the base Controller
class, which yours do.
Just do:
namespace Acme\CompanyBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
/**
* Company controller.
*
*/
class CompanyController extends Controller
{
public function getData()
{
$userObj = $this->get('security.context')->getToken()->getUser();
}
}
Upvotes: 2