How to get more than Request in Controller Action

This post is deprecated since May 2017
You can inject services into actions using controller.service_arguments tag since Symfony 3.3.

You already know you can get Request object in your controller action. Cool, but there is more.

In Symfony 3.1 is new Action Argument Resolving feature, so you can get any service you need. With a bit of work. Today I will show you how.

Disclaimer: What happened to controller constructor injection?

I still prefer constructor injection in controllers. Are you asking why and how to achieve that in Symfony?

In 3 minutes you will find out in my other article. I will wait here...




...ok. Now you are probably in one of these 2 groups:

1. You want to use constructor injection in controllers, because you like advantages of service design

Stop reading, because this article describes only method injection, which is not so clean. It would add unnecessary complexity to your already solid system with no added value. So go install Symplify/ControllerAutowire bundle and enjoy your day!

2. You consider constructor injection in controller too much writing with not much added value

This is article for you. Keep reading!

To be honest, first I was completely ignoring this second group, but Jáchym explained me why it's important.

How named services bring less writing

Typical controller in Symfony looks like this:

// src/AppBundle/Controller/MeetupController.php
namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class MeetupController extends Controller
{
    public function listAction()
    {
        $meetupRepository = $this->get('meetup_repository');

        return $this->render('meetup/list.twig', [
            'meetups' => $meetupRepository->findAll()
        ]);
    }
}

These 2 lines are the most important:

$meetupRepository = $this->get('meetup_repository');
['meetups' => $meetupRepository->findAll()]

Hidden vendor lock

How do we know, that meetup_repository service has findAll() method?

You need 3 things to work at once:

Is this really necessary?

Nope. Any IDE can autocomplete on object or interface typehint. And without plugins.

But how to get that there? We can use constructor injection with typehints, but it would be too much writing.

Compare yourself this:

/**
 * @var MeetupRepository
 */
private $meetupRepository;

public function __construct(MeetupRepository $meetupRepository)
{
    $this->meetupRepository = $meetupRepository;
}

public function listAction()
{
    // $this->meetupRepository;
}

to this:

public function listAction()
{
    // $this->get('meetup_repository');
}

I've counted that for you:

It's 11 lines to 1 just to just get a service!

I must admit, this is killer argument why not to use constructor injection in controllers.

Meet me half way?

What if you could inject the service via method?

public function listAction(MeetupRepository $meetupRepository)
{
    $meetups = $meetupRepository->findAll();
    // ...
}

Result?

This all brings greater secondary advantages:

To make this happened, I made Symplify\ActionAutowire bundle.

How to enable controllers action autowiring in 3 steps

1. Install package

composer require symplify/action-autowire

2. Register bundle

// app/AppKernel.php
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = [
            new Symplify\ActionAutowire\SymplifyActionAutowireBundle(),
            // ...
        ];
    }
}

3. Add some dependency for your controller via constructor

// src/AppBundle/Controller/MeetupController.php
namespace AppBundle\Controller;

class MeetupController extends Controller
{
    public function listAction(MeetupRepository $meetupRepository)
    {
        return $this->render('meetup/list.twig', [
            'meetups' => $meetupRepository->findAll()
        ]);
    }
}

And that's it!

For further use, just check Readme for Symplify/ActionAutowire.

Made for you

Missing some feature or found a bug? Let me know. I want to make this package suit your needs and work as best as possible.


Found a typo? Fix it to join team of 64 people that improve content here

❤️️ Do you like what I write about? Or do you hate it but enjoy discussion? 😠
You can support my writing by throwing a couple bucks at my Patreon