Symfony v3.3.6 неожиданное поведение службы

Я работаю над проектом Symfony3 и играю с «новым» механизмом внедрения зависимостей. Может кто-нибудь, пожалуйста, объясните мне следующее поведение, пожалуйста:

это моя установка:


services.yml

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

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

  MyBundle\A: 
    public:false

Контроллер Сценарий А

<?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(); 
    }
}

Контроллер Сценарий 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(); 
    }
}

Я пытаюсь получить службу A внутри indexAction из контейнера. Поскольку я пометил его как приватный в своем services.yml, я ожидаю исключения при попытке его захватить (как в Scenario B). Но в Scenario A я не получаю исключение, потому что служба A уже была внедрена (автоматически подключена) в контроллер.

(здесь (ожидаемое) исключение из сценария B: You have requested a non-existent service "MyBundle\A".)

Может кто-нибудь объяснить это поведение, пожалуйста.

ваше здоровье


person Friedrich Roell    schedule 08.08.2017    source источник


Ответы (2)


После небольшого объяснения в комментариях я понимаю ваш вопрос как:

Как частный сервис становится общедоступным по запросу в действии контроллера?

При внедрении действия эти собранные сервисы перерегистрируются с классом ServiceLocator, что делает их доступными с ->get().

См. RegisterControllerArgumentLocatorsPass здесь.

введите здесь описание изображения

Я согласен, что это немного непонятное поведение. Думаю, не все пути можно пройти.

person Tomas Votruba    schedule 18.05.2018
comment
это не отвечает на вопрос - person Friedrich Roell; 19.05.2018
comment
Так и есть, поскольку оба сценария недействительны. Не могли бы вы объяснить немного больше? Ты это пробовал? - person Tomas Votruba; 19.05.2018
comment
Нет, сценарий А вполне подходит. Вы говорите о внедрении метода, а я говорю о symfonys DI. - person Friedrich Roell; 21.05.2018
comment
Это работает, это правда, но недействительно. Вам требуется служба в аргументе метода, а затем снова из контейнера DI. Нет необходимости, он у вас уже есть :) Оба ваших сценария представляют собой внедрение методов в Symfony DI. - person Tomas Votruba; 21.05.2018
comment
Да, я просто ссылаюсь на его неверный код, который вызовет у вас больше WTF в будущем, например: symfony.com/blog/ Обычно фреймворк не ожидает каждого варианта использования, который люди используют, и выдает приятное информативное исключение. Это не их работа. Они относятся к наиболее распространенным случаям, которые было бы слишком дорого покрывать самостоятельно. - person Tomas Votruba; 21.05.2018
comment
Но к вашему ответу: я предполагаю, что с инъекцией действия эти собранные сервисы перерегистрируются в классе ServiceLocator, что делает их доступными с помощью ->get(): см. здесь: github.com/symfony/symfony/commit/ - person Tomas Votruba; 21.05.2018
comment
Если этот WTF все еще остается в Symfony 3.4, вы можете сообщить о нем как о проблеме: github.com/symfony/symfony /issues Думаю, команда Symfony не захочет это исправлять - person Tomas Votruba; 21.05.2018
comment
спасибо, перерегистрация действительно объясняет сценарий А. Это приводит к очень странному поведению в отношении видимости/доступности сервисов. - person Friedrich Roell; 22.05.2018
comment
Спасибо за усилия - person Friedrich Roell; 22.05.2018
comment
Рад помочь! Спасибо за ваше терпение - person Tomas Votruba; 22.05.2018

Недопустимое поведение приватных сервисов описано здесь: http://symfony.com/blog/new-in-symfony-3-2-improved-private-services

Запрос частной службы с помощью метода Container::get() устарел в Symfony 3.2 и больше не возвращает службу в 4.0.

Регистрирует ли он какие-либо «устаревшие» в журнале разработчиков?

person JerzySBG    schedule 24.08.2017