如何使用 PHP 反射 API 编写和使用 PHP 依赖注入容器

How to write and use a PHP Dependency Injection Conatiner using PHP Reflection API

我正在尝试在纯 OOP 应用程序中实现简单的 DI。我想使用依赖注入来管理许多服务(数据库、RequestValidator、缓存等)。我已经阅读了很多博客并且喜欢this one from tech-tajawal but I could not really understand where should I include the container that tech-tajawal wrote。有人可以告诉我怎么做吗?

我希望它干净,因此想使用基于构造函数的注入。所以如果我有一个 class,假设 AbstractBaseController 将注入一个名为 Request 的依赖项,所以我会写:

php:

<?php

     namespace src\controllers;
     use system\middlewares\Request as Request;

     abstract class AbstractBaseController {

         private $request;

         public function __construct(Request $request) {
             $this->request = $request;
             return $this;
         }

     }

但这只会抛出

Fatal error: Uncaught TypeError: Argument 1 passed to src\controllers\AbstractBaseController::__construct() must be an instance of system\middlewares\Request, none given`

我认为 the container from tech-tajawal 必须以某种方式包含在我的项目根目录中,但我不知道如何。

请原谅我的天真,因为我一直依赖于框架。

您应该在应用程序的最开始实例化您的容器(考虑一个 bootstrap class,或者甚至在 index.php 本身的顶部,考虑一个非常简单的应用程序),因为您需要在所有后续服务实例化之前准备好容器。

唯一可能在容器实例化之前执行的是与配置相关的事情,因为这些通常是容器正常工作所必需的(配置参数、PSR-4 自动加载配置等)。

例如,假设您有一个名为 MyController 的 class,它扩展了摘要 class AbstractBaseController.

然后,在 index.php,例如,您可以实例化您的容器和控制器:

//index.php
$container = new Container();
$controller = $container->get('namespace\of\MyController');
$controller->render();

当您这样做时,来自构造函数的所有依赖项都将由容器库的自动装配模块处理。

在实际应用中,控制器的实例化通常在路由器内部处理,路由器将 URL 地址、方法和参数映射到不同的 classes 以由容器加载.

自动装配的一个经验法则是,你永远不能再直接调用 new namespace\of\MyController(),因为手动实例化它需要你传递每个构造函数依赖项(所以你并没有真正使用自动装配功能).实例化它的正确方法始终是使用 $container->get('namespace\of\MyController').