Symfony DI: Uncaught ArgumentCountError: Too few arguments to function App::__construct(), 0 passed in index.php on line 28 and exactly 1 expected

Symfony DI: Uncaught ArgumentCountError: Too few arguments to function App::__construct(), 0 passed in index.php on line 28 and exactly 1 expected

我正在尝试实现 Symfonys 依赖注入容器。

我设置了 2 个容器,一个用于数据库,一个用于系统用户。

并且我正在对 App class 和 SystemUser class 使用 addArgument(),推送到 App class 一个 SystemUser 对象,对于 SystemUser class 一个 Database 对象。

index.php:

require_once 'vendor/autoload.php';

use TestingDI\App;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

$containerBuilder = new ContainerBuilder();
$containerBuilder->register('database', '\TestingDI\Database');

$containerBuilder->register('system.user', '\TestingDI\SystemUser')
                 ->addArgument(new Reference('database'));

$containerBuilder->register('app', '\TestingDI\App')
                 ->addArgument(new Reference('system.user'));


$database       = $containerBuilder->get('database');
$systemUser     = $containerBuilder->get('system.user');
$app            = $containerBuilder->get('app');

# Initialize App class
$app = new App();

App.php:

<?php 

namespace TestingDI;

use TestingDI\SystemUser; 


class App {

    public $systemUser; 

    public function __construct(SystemUser $systemUser)
    {
        var_dump($systemUser);
    }
}

我确实看到了我的 var_dump 结果和对象,但不断收到此错误:

PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function TestingDI\App::__construct(), 0 passed in /www/potato/symfony-di/index.php on line 28 and exactly 1 expected in /www/potato/symfony-di/testingdi/App.php:12

Stack trace:

0 /www/potato/symfony-di/index.php(28): TestingDI\App->__construct()

1 {main} thrown in /www/potato/symfony-di/testingdi/App.php on line 12

这些是我的其他 classes:

SystemUser.php

<?php 
namespace TestingDI;

use TestingDI\Database;

class SystemUser {

    public $db; 

    public function __construct( Database $database )
    {
        $this->db = $database;
    }
}

Database.php

<?php 
namespace TestingDI;

class Database {

    public function __construct()
    {

    }
}

似乎对什么是依赖注入以及如何使用它存在基本的误解。

由于您使用依赖容器来构建应用程序的不同部分,因此您应该从容器获取这些对象,而不是直接实例化它们。

而且,如果您要直接实例化它们(例如 new App()),您需要遵守常规语言规则。在这种情况下,构造函数的签名:

public function __construct(SystemUser $systemUser)

如果你调用构造函数而不向它传递 SystemUser class 的对象,它将失败,同样地,如果你调用它,任何其他 method/function 都会失败一种不符合其签名的方式。

到你做的时候

$app            = $containerBuilder->get('app');

您的应用已经 "initialized",您根本不需要调用 new

通过这样做:

$containerBuilder = new ContainerBuilder();
$containerBuilder->register('database', '\TestingDI\Database');

$containerBuilder->register('system.user', '\TestingDI\SystemUser')
                 ->addArgument(new Reference('database'));

$containerBuilder->register('app', '\TestingDI\App')
                 ->addArgument(new Reference('system.user'));


$database       = $containerBuilder->get('database');
$systemUser     = $containerBuilder->get('system.user');
$app            = $containerBuilder->get('app');

您所做的相当于:

$database   = new Database();
$systemUser = new SystemUser($database);
$app        = new App($systemUser);

只有您让 DI 容器为您完成工作。当然,考虑到您的容器定义冗长,这似乎有点毫无意义。

但您可以让 autowiring 的力量为您完成大部分繁重的工作,并执行以下操作:

$container = new ContainerBuilder();
$container->autowire( Database::class );
$container->autowire( SystemUser::class );
$container->autowire( App::class )
          ->setPublic( true );

$container->compile();

// this will get you an application instance with all the dependencies
// resolved and injected in the class.
$app = $container->get( App::class );

我现在注意到你在 时已经遇到了类似的问题,我现在意识到整个问题都围绕着对 DI 容器处理什么问题的简单误解