41

I need to access a method from a different controller inside another controller. How can I do it? Can I use this->get method?

Can I include the controller inside my current controller and make a object of it and access the method via the object? Is it "ok" to do it this way?

I want to call the form method --- newAction of the other controller.

BlitZ
  • 12,038
  • 3
  • 49
  • 68
chirag7jain
  • 1,485
  • 3
  • 26
  • 43

3 Answers3

73

If you don't want to define the class as a service, as it doesn't feel as a good practice to me and @Qoop quoted Fabien saying the same, you can use forwarding:

http://symfony.com/doc/current/controller/forwarding.html

public function indexAction($name)
{
    $response = $this->forward('AcmeHelloBundle:Hello:fancy', array(
        'name'  => $name,
        'color' => 'green',
    ));

    // ... further modify the response or return it directly

    return $response;
}

If you need to embed the output of an internal controller-action in a template, the documentation for Symfony also has something for that.

Gianfranco P.
  • 10,049
  • 6
  • 51
  • 68
SimonSimCity
  • 6,415
  • 3
  • 39
  • 52
  • this is wrong as it will generate response using template of fancy action instead of template associated with indexAction – gondo Jan 30 '14 at 17:24
  • 1
    @gondo, you mean, if you use templates by annotations? Yepp. That's right. Then you'll get the generated template - so the response as it would've been sent back. If you want to get the data before annotations are used, then you have to define the class as service. – SimonSimCity Jan 30 '14 at 21:24
  • I see way bigger problems regarding the "forwarding" when it comes to unit testing. You won't be able to mock the subrequest, when you instead define your controller as a service, you can easily mock it. – user3746259 Feb 23 '16 at 00:07
  • 1
    @user3746259 If you want to write unit-tests for your controllers, I recommend reading this answer: http://stackoverflow.com/questions/10126826/how-can-i-unit-test-a-symfony2-controller#10132372 – SimonSimCity Feb 23 '16 at 07:06
  • I know how to write them (I recommended you do write some Unit Tests for the Controllers) and thats why I said don't use the forwarding Option, or what do you mean? – user3746259 Feb 23 '16 at 11:37
  • 1
    @user3746259, please read the accepted answer. The answer is not about "how to", but more about how to test controllers. I agree with the author that unit-tests aren't the right tool for testing controllers. Functional-tests are. – SimonSimCity Feb 23 '16 at 14:10
  • Yep, and I said that I would unit test controllers a bit - for functional tests I'm using behat thats ok. There is no right answer if you should unit test parts of a controller or only do functional tests. I think it is important that you do functional tests (e.g. with behat) and in addition, you could do some unit tests. And when it comes to unit tests, you should not use the "forward" method because it generates a new request internally and you would need to mock a lot. Thats what I wanted to point out. Regards. – user3746259 Feb 23 '16 at 14:17
47

You can define your controller as service, then get it in another controller.

In your services.yml define needed controller as a service:

services:
    your_service_name:
        class: YourCompany\YourBundle\Controller\YourController

Then in any controller you'll be able to get this service via container:

$yourController = $this->get('your_service_name');

There is some useful information about Controllers as Services in documentation

Vitalii Zurian
  • 17,858
  • 4
  • 64
  • 81
  • 3
    Is this the best way to do it. Or is there another way to do it – chirag7jain Apr 05 '13 at 06:47
  • @CJ Well, as it was mentioned in comments, you shouldn't call controller action in another controller. But from Symfony2 POV - having controller defined as service is OK – Vitalii Zurian Apr 05 '13 at 06:59
  • Thanks a lot. I just wanted to make sure I am following the best parctice – chirag7jain Apr 05 '13 at 07:06
  • 1
    I am getting this error **FatalErrorException: Error: Call to a member function get() on a non-object in /home/cj/public_html/Symfony/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php line 163. The method which I am trying to call does exist. Can you help. I have defined the service exactlty the way you told me – chirag7jain Apr 05 '13 at 07:46
  • 2
    Services as controllers are not recommended, at least not by Febien - see: https://github.com/symfony/symfony-docs/issues/457 – qooplmao Apr 05 '13 at 08:36
  • So the answer was accepted. Did you get past the error message? Did you read the cookbook entry and realize that it's up to you to inject additional services into you controller when defining it as a service? – Cerad Apr 05 '13 at 12:57
  • How can you execute a method (which is not an Action and which is inside `YourController`) using the service? Thank you – Adib Aroui Apr 20 '15 at 15:18
  • @qooplmao I have a subform/controller that needs to get presented on the same page... forwarding doesn't seem to be the answer. I just went with a static method and passed the context. – Ray Foss Sep 19 '16 at 18:08
  • Another way could be to allow all your controllers to be used as Services. See this [SO post](https://stackoverflow.com/questions/8342031/symfony2-use-doctrine-in-service-container/45269646#45269646). Also, if they aren't used, there is no performance cost! – Niket Pathak Jul 31 '17 at 16:28
1

You just have to instantiate the controller you want to access in the controller you are in.

The controller you are in:

*In symfony 2/3 you may have to put "YourBundle" instead of "App"

..

use App\Controller\DefaultController; 

..

public function index()
{

    $default_controller = new DefaultController;
    $variable = 1;
    $default_controller->actionToCall($variable);

    return $this->render('...'); //The view you want to render or call another action
}

In the controller called:

public function actionToCall($variable)
{
    //dd($variable);        
}

Done.

Lucian
  • 19
  • 1