本文目录导读:

我来通过一个实际例子,详细介绍PHP依赖注入容器(DIC)的用法。
什么是依赖注入容器
依赖注入容器是管理类依赖的工具,它负责:
- 创建对象及其依赖
- 存储已注册的服务
- 自动解析依赖关系
基本使用示例
使用Pimple容器(最流行的轻量级容器)
<?php
// 1. 安装
// composer require pimple/pimple
// 2. 基本容器使用
require 'vendor/autoload.php';
use Pimple\Container;
$container = new Container();
// 注册服务(延迟加载)
$container['db'] = function ($c) {
return new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
};
// 使用服务
$db = $container['db'];
完整业务示例
<?php
use Pimple\Container;
class UserRepository
{
private $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
public function findUser($id)
{
$stmt = $this->db->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$id]);
return $stmt->fetch();
}
}
class UserService
{
private $userRepository;
private $logger;
public function __construct(UserRepository $userRepository, Logger $logger)
{
$this->userRepository = $userRepository;
$this->logger = $logger;
}
public function getUserProfile($userId)
{
$this->logger->log("Fetching user: $userId");
return $this->userRepository->findUser($userId);
}
}
class Logger
{
public function log($message)
{
echo "[LOG] $message\n";
}
}
// 配置容器
$container = new Container();
// 注册基础服务
$container['db'] = function ($c) {
return new PDO('mysql:host=localhost;dbname=test', 'root', 'password');
};
$container['logger'] = function ($c) {
return new Logger();
};
// 注册业务服务
$container['user_repository'] = function ($c) {
return new UserRepository($c['db']);
};
$container['user_service'] = function ($c) {
return new UserService(
$c['user_repository'],
$c['logger']
);
};
// 使用容器获取服务
$userService = $container['user_service'];
$user = $userService->getUserProfile(123);
print_r($user);
使用PHP-DI(功能更完整的容器)
<?php
// 安装
// composer require php-di/php-di
use DI\Container;
use DI\ContainerBuilder;
// 创建容器
$containerBuilder = new ContainerBuilder();
$containerBuilder->useAutowiring(true); // 启用自动装配
$container = $containerBuilder->build();
// 简单使用 - 自动解析依赖
class Mailer
{
public function send($to, $message)
{
echo "Sending mail to $to: $message\n";
}
}
class UserNotifier
{
private $mailer;
public function __construct(Mailer $mailer)
{
$this->mailer = $mailer;
}
public function notifyUser($userId)
{
$this->mailer->send("user$userId@example.com", "Welcome!");
}
}
// 容器自动解析所有依赖
$notifier = $container->get(UserNotifier::class);
$notifier->notifyUser(1);
// 手动配置
$containerBuilder->addDefinitions([
Mailer::class => function () {
return new Mailer();
},
// 也可以绑定接口
'Logger' => function () {
return new Logger();
},
]);
// 使用参数注入
class EmailService
{
private $smtpHost;
private $smtpPort;
public function __construct($smtpHost = 'localhost', $smtpPort = 25)
{
$this->smtpHost = $smtpHost;
$this->smtpPort = $smtpPort;
}
}
$containerBuilder->addDefinitions([
EmailService::class => function () {
return new EmailService('smtp.example.com', 587);
},
]);
使用Laravel的服务容器
<?php
// Laravel框架中的使用
// 1. 绑定服务
app()->bind('PaymentGateway', function ($app) {
return new PaymentGateway('api-key');
});
// 2. 单例绑定
app()->singleton('Logger', function ($app) {
return new Logger();
});
// 3. 自动注入到控制器
class OrderController extends Controller
{
private $paymentGateway;
// Laravel自动解析依赖
public function __construct(PaymentGateway $paymentGateway)
{
$this->paymentGateway = $paymentGateway;
}
public function processOrder()
{
return $this->paymentGateway->charge();
}
}
// 4. 使用门面/Facade
public function test()
{
$payment = app('PaymentGateway');
$logger = app('Logger');
}
自定义简单容器
<?php
class SimpleContainer
{
private $bindings = [];
private $instances = [];
// 绑定服务
public function bind($abstract, $concrete = null)
{
$this->bindings[$abstract] = $concrete ?? $abstract;
}
// 绑定单例
public function singleton($abstract, $concrete = null)
{
$this->bind($abstract, $concrete);
$this->bindings[$abstract] = function ($container) use ($abstract) {
if (!isset($this->instances[$abstract])) {
$this->instances[$abstract] = $container->build($abstract);
}
return $this->instances[$abstract];
};
}
// 解析服务
public function make($abstract)
{
if (isset($this->bindings[$abstract])) {
$binding = $this->bindings[$abstract];
if ($binding instanceof \Closure) {
return $binding($this);
}
return $this->build($binding);
}
return $this->build($abstract);
}
// 自动构建类(实现简单的自动注入)
private function build($class)
{
$reflector = new ReflectionClass($class);
if (!$reflector->isInstantiable()) {
throw new Exception("Class $class is not instantiable");
}
$constructor = $reflector->getConstructor();
if (is_null($constructor)) {
return new $class;
}
$parameters = $constructor->getParameters();
$dependencies = [];
foreach ($parameters as $parameter) {
$dependency = $parameter->getType();
if ($dependency && !$dependency->isBuiltin()) {
// 递归解析依赖
$dependencies[] = $this->make($dependency->getName());
} else {
// 基本类型参数,检查是否有默认值
if ($parameter->isDefaultValueAvailable()) {
$dependencies[] = $parameter->getDefaultValue();
} else {
throw new Exception("Cannot resolve dependency");
}
}
}
return $reflector->newInstanceArgs($dependencies);
}
}
// 使用自定义容器
$container = new SimpleContainer();
// 注册服务
$container->bind('Logger', function () {
return new Logger();
});
// 自动解析UserService及其所有依赖
$userService = $container->make(UserService::class);
最佳实践
<?php
// 1. 使用接口抽象
interface PaymentGatewayInterface
{
public function charge(float $amount);
}
class StripeGateway implements PaymentGatewayInterface
{
public function charge(float $amount)
{
// 实现
}
}
class PaypalGateway implements PaymentGatewayInterface
{
public function charge(float $amount)
{
// 实现
}
}
// 2. 配置驱动
$config = [
'payment_gateway' => 'stripe',
];
$container['payment_gateway'] = function ($c) use ($config) {
switch ($config['payment_gateway']) {
case 'stripe':
return new StripeGateway();
case 'paypal':
return new PaypalGateway();
default:
throw new \Exception('Unknown gateway');
}
};
// 3. 延迟加载
$container['heavy_service'] = function ($c) {
// 仅有需要时才创建
return new HeavyService();
};
注意事项
- 性能考虑:使用
singleton减少重复创建 - 调试方便:容器应该支持查看已注册的服务
- 避免服务定位器反模式:不要过度依赖容器
- 依赖关系清晰:尽量明确显式的依赖
依赖注入容器的核心优势:
- 解耦:类之间不直接实例化依赖
- 可测试性:方便替换mock对象
- 可维护性:统一管理服务
- 灵活性:方便切换实现
选择合适的容器(Pimple、PHP-DI或框架内置的)取决于项目复杂度和你需要的高级特性。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播