Symfony 4:DependencyInjection组件 - 未捕获的ReflectionException:类不存在

2 php dependency-injection autowired symfony

我正在尝试将Symfony(版本4.0.0)中的DependencyInjection组件实现到我的项目中.为此,我按照以下简单步骤,以了解自动装配过程:

  • composer.json:Appsrc文件夹分配名称空间.
  • services.yaml:Appsrc文件夹分配名称空间.
  • 在命名空间下的文件夹中定义MyController类.srcApp\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
Run Code Online (Sandbox Code Playgroud)

错误发生在方法中的这一行(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()));

    //..
}
Run Code Online (Sandbox Code Playgroud)

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/
Run Code Online (Sandbox Code Playgroud)

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/"
    }
}
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

配置/ 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}'
Run Code Online (Sandbox Code Playgroud)

SRC /控制器/ myController的

<?php

namespace App\Controller;

class MyController {

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

}
Run Code Online (Sandbox Code Playgroud)

更新1:

用容器编译后 compile()

$loader->load('services.yaml');
$container->compile();
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

( ! ) 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
Run Code Online (Sandbox Code Playgroud)

$container->definitionscompile()电话后检查了数组.我意识到在编译过程中从数组中删除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."
Run Code Online (Sandbox Code Playgroud)

Cer*_*rad 6

我继续设置一个新项目.

您的设置存在两个问题.

首先,您需要在使用之前编译容器:

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

$container->compile();

$myController = $container->get(MyController::class);
Run Code Online (Sandbox Code Playgroud)

然后,您需要先将控制器服务公开,然后再将其从容器中拉出来:

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

App\Controller\:
    resource: 'src/Controller/*'
    public: true
Run Code Online (Sandbox Code Playgroud)

这基本上就是框架的作用.