Symfony DI:未捕获的ArgumentCountError:函数App :: __ construct()的参数太少,第28行的index.php中传递了0,而预期的恰好是1

时间:2019-01-14 14:13:08

标签: php symfony dependency-injection symfony-dependency-injection

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

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

并且我在addArgument()类和App类上都使用“ SystemUser”,将App对象推到SystemUser类,并为SystemUser类的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致命错误:未捕获ArgumentCountError:函数TestingDI \ App :: __ construct()的参数太少,第28行的/www/potato/symfony-di/index.php中传递了0,而在/ www /中恰好期望了1马铃薯/symfony-di/testingdi/App.php:12

     

堆栈跟踪:

     

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

     

1 {main}     在第12行的/www/potato/symfony-di/testingdi/App.php中抛出

这些是我的其他课程:

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()
    {

    }
}

1 个答案:

答案 0 :(得分:3)

关于什么是依赖注入以及如何使用它似乎有一个基本的误解。

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

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

public function __construct(SystemUser $systemUser)

如果在不向构造函数传递SystemUser类对象的情况下调用构造函数,则构造函数将失败,与其他任何方法/函数的调用方式都不相同,否则将失败它的签名。

到你做的时候

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

您的应用已经“初始化”了,您根本不需要调用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 );

我现在注意到您在trying a different DI library时已经遇到了类似的问题,并且我现在意识到整个问题都围绕着一个简单的误解,即对DI容器要处理的问题的误解