Search code examples
phpdependency-injectionautowiredsymfony-3.3

symfony v3.3.6 unexpected service behaviour


Im working on a Symfony3 project and playing around with the "new" dependency injection mechanism. can some please explain the following behavior to me please:

this is my setup:


services.yml

services:
  _defaults:
    autowire: true
    autoconfigure: true
    public: false

  MyBundle\Controller\:
    resource: '../../Controller/'
    public: true
    tags: ['controller.service_arguments']

  MyBundle\A: 
    public:false

Controller Scenario A

<?php

namespace MyBundle\Controller;

use ...

class RootController extends Controller
{
    /**
     * @Route("/", name="root")
     */
    public function indexAction(A $a) <- INJECTION HERE
    {
        $b = $this->get(A::class); // NO EXCEPTION THROWN HERE

        return new Response(); 
    }
}

Controller Scenario B

<?php

namespace MyBundle\Controller;

use ...

class RootController extends Controller
{
    /**
     * @Route("/", name="root")
     */
    public function indexAction() // <- NO INJECTION
    {
        $b = $this->get(A::class); // EXCEPTION THROWN HERE

        return new Response(); 
    }
}

Im trying to fetch service A inside the indexAction from the container. As I marked it private in my services.yml I'm expecting an Exception when trying to grab it (like in Scenario B). But in Scenario A I'm not getting an Exception because the service A has already been injected (auto wired) into the Controller.

(here the (expected) Exception of Scenario B: You have requested a non-existent service "MyBundle\A".)

Can some explain this behaviour please.

cheers


Solution

  • After bit of explaining in the comments I understand your question as:

    How does a private service becomes public by request in the controller action?

    With action injection these services collected are re-registred with ServiceLocator class, which make it accessible with ->get().

    See RegisterControllerArgumentLocatorsPass here.

    enter image description here

    I agree it's a bit unclear behavior. Not all paths can be covered I guess.