Reputation: 3581
I have a controller that forwards the whole request to another controller.
The first controller is Version1Controller
, and $this->controller
is not null, giving me access to services. It forwards the request to GetUserTrialsController
defined in services as controller.get_user_trials
. In the second controller $this->container
is null. How come symfony loses it half way through? Is there any way to pass the container around?
Below is the code to demonstrate the behaviour
services.yml
services:
controller.get_user_trials:
class: AppBundle\Controller\GetUserTrialsController
Version1Controller.php
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class Version1Controller extends Controller
{
public function indexAction(Request $request)
{
var_dump("V1Controller " . json_encode(is_null($this->container)));
return $this->forward("controller.get_user_trials:indexAction");
}
}
GetUserTrials.php
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class GetUserTrialsController extends Controller
{
public function indexAction(Request $request)
{
var_dump("GetUserTrials " . json_encode(is_null($this->container)));
return "abc";
}
}
The output:
string(18) "V1Controller false"
string(13) "GetUserTrials true"
abc
Upvotes: 2
Views: 71
Reputation: 48865
Just to amplify a bit on what @qooplmao has said. It is important to understand that there are two distinct ways to instantiate a controller.
The most common way is is by specifying a three part controller string. Something like MyBundle:MyController:my. When a string like this is encountered the routing system determines the controller class, instantiates a new object and then calls setContainer to inject the container.
You can however define a controller as a service by using a string with only two parts. When you do this the routing system simply pulls the object from the container with no additional processing. It's entirely possible that your controller does not need the container at all so there is no point in injecting it.
In your case, just add a call to setContainer in your service definition.
services:
controller.get_user_trials:
class: AppBundle\Controller\GetUserTrialsController
calls: [[setContainer, ['@service_container']]]
And all will be well. Or don't define your controller as a service and just use:
$this->forward("AppBundle:GetUserTrials:index");
I happen to like defining controllers as services but the standard approach works fine for most cases.
Upvotes: 3