Symfony 4: компонент DependencyInjection — Uncaught ReflectionException: класс не существует

Я пытаюсь реализовать Компонент DependencyInjection из Symfony (версия 4.0.0) в мой проект. Для этого я выполнил следующие простые шаги, чтобы понять автоматическое связывание процесс:

  • В composer.json: Назначить пространство имен App к src папка.
  • В services.yaml: Назначить пространство имен App к src папка.
  • определять MyController класс в src папка, под пространством имен App\Controller,
  • В bootstrap.php: Создать ContainerBuilder пример ($container).
  • В bootstrap.php: Создать YamlFileLoader Объект и загрузить файл конфигурации services.yaml внутрь.
  • В bootstrap.php: Получить экземпляр MyController от $container и отобразить его на экране.

Но я продолжаю получать следующую ошибку:

( ! ) Fatal error: Uncaught ReflectionException: Class does not exist in <path-to-my-project-root>/vendor/symfony/dependency-injection/ContainerBuilder.php on line 1051
( ! ) ReflectionException: Class does not exist in <path-to-my-project-root>/vendor/symfony/dependency-injection/ContainerBuilder.php on line 1051
Call Stack
#   Time    Memory  Function    Location
1   0.0160  354632  {main}( )   .../index.php:0
2   0.0166  357928  require_once( '<path-to-my-project-root>/bootstrap.php' ) .../index.php:7
3   0.0872  1752040 Symfony\Component\DependencyInjection\ContainerBuilder->get( )  .../bootstrap.php:16
4   0.0872  1752040 Symfony\Component\DependencyInjection\ContainerBuilder->doGet( )    .../ContainerBuilder.php:522
5   0.0872  1752816 Symfony\Component\DependencyInjection\ContainerBuilder->createService( )    .../ContainerBuilder.php:555
6   0.0873  1752928 __construct ( ) .../ContainerBuilder.php:1051

Ошибка возникает в этой строке (1051) в ContainerBulder::createService метод, потому что $definition->getClass() возвращается NULL:

private function createService(Definition $definition, array &$inlineServices, $id = null, $tryProxy = true) {
// Line 1051:
$r = new \ReflectionClass($class = $parameterBag->resolveValue($definition->getClass()));

//..
}

В главе Автоматическая загрузка услуг в services.yaml, как я понял, используя только те настройки без каких-либо других настроек в services.yamlконтейнер DI будет знать, как создать экземпляр MyController, Может я не прав? …

Не могли бы вы взять секунду, чтобы помочь мне? Большое спасибо.


Мой проект состоит из следующей структуры и файлов:

Структура проекта

bootstrap.php
composer.json
config/
services.yaml
src/
Controller/
MyController
vendor/
symfony/
config/
dependency-injection/
filesystem/
polyfill-mbstring/
yaml/

composer.json

"require": {
"php": ">=5.5.0",
"symfony/dependency-injection": "^4.0",
"symfony/config": "^4.0",
"symfony/yaml": "^4.0",
},
"autoload": {
"psr-4": {
"App\\": "src/"}
}

bootstrap.php

<?php

use App\Controller\MyController;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

require '../vendor/autoload.php';

$container = new ContainerBuilder();

$fileLocator = new FileLocator(__DIR__ . '/config');
$loader = new YamlFileLoader($container, $fileLocator);
$loader->load('services.yaml');

$myController = $container->get(MyController::class);

var_dump($myController);

конфиг / services.yaml

services:
# default configuration for services in *this* file
_defaults:
autowire: true      # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false       # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.

# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{Entity,Migrations,Tests}'

SRC / Controller / MyController

<?php

namespace App\Controller;

class MyController {

public function myAction() {
echo 'Hello from MyController.';
}

}

Обновление 1:

После компиляции контейнера с compile()

$loader->load('services.yaml');
$container->compile();

Я получил следующую ошибку:

( ! ) Fatal error: Uncaught Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "App\Controller\MyController". in <my-project-path>/vendor/symfony/dependency-injection/ContainerBuilder.php on line 950
( ! ) Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "App\Controller\MyController". in <my-project-path>/vendor/symfony/dependency-injection/ContainerBuilder.php on line 950
Call Stack
#   Time    Memory  Function    Location
1   0.1512  357648  {main}( )   .../index.php:0
2   0.1675  361056  require_once( '<my-project-path>/bootstrap.php' )   .../index.php:7
3   3.5621  2582624 Symfony\Component\DependencyInjection\ContainerBuilder->get( ???, ??? ) .../bootstrap.php:18
4   3.5621  2582624 Symfony\Component\DependencyInjection\ContainerBuilder->doGet( ???, ???, ??? )  .../ContainerBuilder.php:522

Я проверил $container->definitions массив после compile() вызов. Я понял, что все услуги (в том числе App\Controller\MyController) сохранены в списке определений до compile() где удалено из массива процессом компиляции.

Больше этого: В $compiler->passConfig->log Я нашел эти записи (после шага компиляции):

[0] string  "Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass: Removed service "Psr\Container\ContainerInterface"; reason: private alias."[1] string  "Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass: Removed service "Symfony\Component\DependencyInjection\ContainerInterface"; reason: private alias."[2] string  "Symfony\Component\DependencyInjection\Compiler\InlineServiceDefinitionsPass: Inlined service "App\Service\MyService" to "App\Controller\MyController"."[3] string  "Symfony\Component\DependencyInjection\Compiler\RemoveUnusedDefinitionsPass: Removed service "App\Controller\MyController"; reason: unused."[4] string  "Symfony\Component\DependencyInjection\Compiler\RemoveUnusedDefinitionsPass: Removed service "App\Service\MyService"; reason: unused."

1

Решение

Я пошел дальше и настроил новый проект.

Есть две проблемы с вашей настройкой.

Сначала вам нужно скомпилировать контейнер перед его использованием:

// bootstrap.php
$loader->load('services.yaml');

$container->compile();

$myController = $container->get(MyController::class);

И затем вам нужно сделать службу контроллера общедоступной, прежде чем извлекать ее из контейнера:

// services.yaml
App\:
resource: 'src/*'
exclude: 'src/{Entity,Migrations,Tests}'

App\Controller\:
resource: 'src/Controller/*'
public: true

Это в основном то, что делает фреймворк.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]