如何使用 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')
.
我正在尝试在纯 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')
.