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.

4
  • I think you are not supposed to do that if you are following MVC, you should extract taht function into a Model or helper object. Commented Apr 5, 2013 at 6:37
  • Can you show how to do it the MVC way Commented Apr 5, 2013 at 6:38
  • What do you want with that controller? Commented Apr 5, 2013 at 6:49
  • as long as Symfony has things like "{{ render(controller(...)) }}"" MVC shouldn't be a concern Commented May 14, 2015 at 17:56

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

7 Comments

this is wrong as it will generate response using template of fancy action instead of template associated with indexAction
@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.
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 If you want to write unit-tests for your controllers, I recommend reading this answer: stackoverflow.com/questions/10126826/…
@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.
|
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

9 Comments

Is this the best way to do it. Or is there another way to do it
@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
Thanks a lot. I just wanted to make sure I am following the best parctice
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
Services as controllers are not recommended, at least not by Febien - see: github.com/symfony/symfony-docs/issues/457
|
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.

1 Comment

Or use dependency injection if you need it to work for the whole class.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.