Buy

There is one other piece of auto-registration code in the new services.yml file for Symfony 3.3 involving the Controller/ directory. Copy that!

Then, paste it in our file:

57 lines app/config/services.yml
... lines 1 - 8
services:
... lines 10 - 16
AppBundle\:
... lines 18 - 22
# controllers are imported separately to make sure they're public
# and have a tag that allows actions to type-hint services
AppBundle\Controller\:
resource: '../../src/AppBundle/Controller'
public: true
tags: ['controller.service_arguments']
... lines 29 - 57

This auto-registers each class in src/AppBundle/Controller as a service... which was already done above:

57 lines app/config/services.yml
... lines 1 - 8
services:
... lines 10 - 14
# makes classes in src/AppBundle available to be used as services
# this creates a service per class whose id is the fully-qualified class name
AppBundle\:
resource: '../../src/AppBundle/*'
# you can exclude directories or files
# but if a service is unused, it's removed anyway
exclude: '../../src/AppBundle/{Entity,Repository}'
# controllers are imported separately to make sure they're public
# and have a tag that allows actions to type-hint services
AppBundle\Controller\:
... lines 26 - 57

This overrides those services to make sure that anything in Controller/ is public and has this very special tag. In Symfony 3.3 - controllers are the one service that must be public. And the tag gives us a special controller argument autowiring super power that we'll see soon.

Controllers are Services!?

But wait, our controllers are services!? Yes! In Symfony 3.3, we recommend that all of your controllers be registered as a service. And it's so awesome! You can still use all of your existing tricks. You can still extend Symfony's base Controller class and use its shortcuts. You can even still fetch public services directly from the container. But now, you can also use proper dependency injection if you want to. And, as long as your service's id is the class name, all of the existing routing config formats will automatically know to use your service. In other words, this just works.

Removing Unnecessary Services

Now that we're auto-registering each class as a service, we can remove these two services:

57 lines app/config/services.yml
... lines 1 - 8
services:
... lines 10 - 32
AppBundle\Twig\MarkdownExtension:
#arguments: ['@app.markdown_transformer']
AppBundle\Security\LoginFormAuthenticator: ~
... lines 37 - 57

They're still being registered, but since we don't need to add any further configuration, they're redundant!

Woohoo! And when we refresh our app, everything still works! Controllers as services with four lines of code!

Leave a comment!

  • 2017-10-19 Diego Aguiar

    Awesome!
    Let's keep learning ;)

  • 2017-10-19 Bettinz

    Thank you, I need to study more about dependency injection. BTW I've moved the logic to user Repository and It works great. Thank you :-)

  • 2017-10-17 Diego Aguiar

    Excellent question, is known that you can use a controller just like a service, but the idea is to take advantage of the "dependency injection" in your controller's actions, instead of retrieving services from the container

  • 2017-10-17 Bettinz

    Great idea..I'll try :-) just a question: if using action from one controller to another isn't recommended, why add Controller as Services in 3.3?

  • 2017-10-16 Diego Aguiar

    Ohh I got you. Of course a I have some ideas, but maybe not good ones! :P

    In that case I would move all that logic to the UserRepository, so you can ask him about the registration number of the user and to do the sum up
    And calling it from EventController would be as easy as


    // EventController
    ....
    $userRepo = $this->getDoctrine()->getRepository(User::class);
    $userRepo->getRegistrationNumber($user);
  • 2017-10-16 Bettinz

    Hello Diego Aguiar , I've an action (getRegistrationNumber) that count users registered to an event and add 1. It's just a test but I want to add some users to an event not just with UserController but with EventController; so, from EventController, I need to know the registration number and the best way to do that was to call the action from UserController. Do you have a better idea? Thanks :-)

  • 2017-10-16 Diego Aguiar

    Hey Bettinz

    I wouldn't recommend to call a controller's action inside another controller, what are you trying to achieve?

    You may like to know that you can initiate another request (call a controllers action) inside a twig's template (More info here: https://symfony.com/doc/cur...

    Cheers!

  • 2017-10-15 Bettinz

    Hello, I'm trying to call an action from a controller to another controller.
    So I've UserController and "getRegistrationNumberAction(Event $event)" and from EventController I call

    $number= $this->get(UserController::class)->getRegistrationNumberAction($workEvent);
    The error appear here:
    $em= $this->getDoctrine()->getManager();
    and the error is: Call to a member function has() on null

    I've modified services.yml with new symfony configurations (autowire, _defaults, etc) so I can't understand what is wrong. Can you help me?
    PS: If I try to dump $this->get(UserController::class) it dump null.
    Thanks