本文目录导读:

我来详细讲解ThinkPHP的依赖注入容器机制。
什么是依赖注入容器
基本概念
依赖注入(DI)是一种设计模式,容器则是管理依赖的中央注册表,ThinkPHP内置了完善的依赖注入容器,支持:
- 自动依赖解析
- 依赖注册
- 依赖管理
- 单例模式
容器的基本使用
1 获取容器实例
<?php
namespace app\index\controller;
use think\Container;
use think\facade\App;
class Index
{
// 方式1:通过全局函数
public function method1()
{
$container = app();
// 或者
$container = Container::getInstance();
}
// 方式2:通过门面
public function method2()
{
$container = App::getInstance();
}
}
2 基础绑定与解析
<?php
namespace app\common\service;
use think\Container;
class ContainerDemo
{
// 绑定接口到实现
public function bindInterface()
{
$container = Container::getInstance();
// 绑定接口到具体类
$container->bind('userService', UserService::class);
// 绑定闭包
$container->bind('logger', function() {
return new Logger('app');
});
// 绑定实例
$userService = new UserService();
$container->instance('userService', $userService);
}
// 解析依赖
public function resolveDependency()
{
$container = Container::getInstance();
// 通过名称解析
$userService = $container->make('userService');
// 通过类名解析
$logger = $container->make(Logger::class);
// 直接调用
$userService = app('userService');
}
}
构造函数注入
1 基础构造函数注入
<?php
namespace app\controller;
use app\common\service\UserService;
use app\common\service\OrderService;
use think\Request;
class UserController
{
protected $userService;
protected $orderService;
// 容器自动注入依赖
public function __construct(UserService $userService, OrderService $orderService)
{
$this->userService = $userService;
$this->orderService = $orderService;
}
public function index()
{
return $this->userService->getUserList();
}
}
2 复杂依赖注入
<?php
namespace app\common\service;
use think\Cache;
use think\Log;
use app\common\model\User;
use app\common\repository\UserRepository;
class UserService
{
protected $userRepository;
protected $cache;
protected $log;
// 多依赖自动注入
public function __construct(
UserRepository $userRepository,
Cache $cache,
Log $log
) {
$this->userRepository = $userRepository;
$this->cache = $cache;
$this->log = $log;
}
}
方法注入
<?php
namespace app\controller;
use think\Request;
use app\common\service\UserService;
class DemoController
{
// 方法参数自动注入
public function getUser(UserService $userService, Request $request)
{
$id = $request->get('id');
return $userService->getUser($id);
}
// 配合依赖标识
public function withDefault(Request $request)
{
// 控制器方法的Request会自动注入,无需手动实例化
return $request->param('name');
}
}
接口绑定与实现
<?php
namespace app\common\contracts;
// 定义接口
interface PaymentInterface
{
public function pay($amount);
public function refund($amount);
}
// 具体实现
namespace app\common\service;
use app\common\contracts\PaymentInterface;
class WechatPayment implements PaymentInterface
{
public function pay($amount)
{
return "微信支付: {$amount}元";
}
public function refund($amount)
{
return "微信退款: {$amount}元";
}
}
class AlipayPayment implements PaymentInterface
{
public function pay($amount)
{
return "支付宝支付: {$amount}元";
}
public function refund($amount)
{
return "支付宝退款: {$amount}元";
}
}
// 业务类
namespace app\common\service;
use app\common\contracts\PaymentInterface;
class PaymentService
{
protected $payment;
// 构造函数注入接口
public function __construct(PaymentInterface $payment)
{
$this->payment = $payment;
}
public function process($amount)
{
return $this->payment->pay($amount);
}
}
绑定配置
<?php
// 配置文件 config/di.php
return [
// 接口绑定
'bind' => [
'app\common\contracts\PaymentInterface' => 'app\common\service\WechatPayment',
'app\common\contracts\SMSSenderInterface' => 'app\common\service\AliyunSMS',
],
// 单例绑定
'singleton' => [
'app\common\service\CacheService',
'app\common\service\ConfigService',
],
];
依赖绑定示例
<?php
namespace app\common\provider;
use think\Container;
use app\common\contracts\PaymentInterface;
use app\common\service\WechatPayment;
use app\common\service\AlipayPayment;
class PaymentProvider
{
public static function register()
{
$container = Container::getInstance();
// 根据配置绑定接口
$paymentType = config('payment.default');
$container->bind(PaymentInterface::class, function() use ($paymentType) {
if ($paymentType === 'alipay') {
return new AlipayPayment();
}
return new WechatPayment();
});
// 绑定单例
$container->bind('paymentService', function() {
static $instance = null;
if ($instance === null) {
$instance = new PaymentService();
}
return $instance;
});
}
}
容器高级用法
1 依赖预处理
<?php
namespace app\common\service;
use think\Container;
class DatabaseService
{
public function boot()
{
$container = Container::getInstance();
// 定义工厂方法
$container->make('db.connection', function() {
$config = [
'type' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'database' => env('DB_NAME', 'thinkphp'),
'username' => env('DB_USER', 'root'),
'password' => env('DB_PASS', '')
];
return new PDO(...);
});
}
}
2 容器的上下文绑定
<?php
namespace app\index\controller;
use think\Container;
class Index
{
public function contextBind()
{
$container = Container::getInstance();
// 上下文绑定
$container->bindTo(ApiController::class, 'logger', FileLogger::class);
$container->bindTo(CliController::class, 'logger', ConsoleLogger::class);
// 获取上下文实例
$apiLogger = $container->resolve(ApiController::class, 'logger');
$cliLogger = $container->resolve(CliController::class, 'logger');
}
}
依赖注入实战示例
1 业务逻辑层
<?php
namespace app\service;
use app\model\User;
use app\repository\UserRepository;
use think\Cache;
use think\Log;
class UserService
{
protected $userRepository;
protected $cache;
protected $log;
public function __construct(
UserRepository $userRepository,
Cache $cache,
Log $log
) {
$this->userRepository = $userRepository;
$this->cache = $cache;
$this->log = $log;
}
public function getUserInfo($id)
{
// 尝试从缓存获取
$cacheKey = 'user:' . $id;
$user = $this->cache->get($cacheKey);
if (!$user) {
$user = $this->userRepository->find($id);
$this->cache->set($cacheKey, $user, 3600);
}
$this->log->info("获取用户信息: {$id}");
return $user;
}
}
2 控制器使用
<?php
namespace app\controller;
use app\service\UserService;
use app\service\OrderService;
use think\Request;
use think\Response;
class UserController
{
protected $userService;
protected $orderService;
public function __construct(UserService $userService, OrderService $orderService)
{
$this->userService = $userService;
$this->orderService = $orderService;
}
public function info($id)
{
$user = $this->userService->getUserInfo($id);
$orders = $this->orderService->getUserOrders($id);
return Response::json([
'user' => $user,
'orders' => $orders
]);
}
}
3 门面模式
<?php
namespace app\facade;
use think\Facade;
class UserService extends Facade
{
protected static function getFacadeClass()
{
return 'app\service\UserService';
}
}
// 使用
namespace app\controller;
use app\facade\UserService;
class UserController
{
public function index()
{
// 通过门面访问
$users = UserService::getUserList();
// 等关于解耦
return $users;
}
}
性能优化建议
1 绑定单例
<?php
namespace app\common\service;
class CacheService
{
public function __construct()
{
// 初始化连接
}
}
// 注册为单例
app()->bind('cacheService', CacheService::class);
app()->make('cacheService'); // 只会实例化一次
2 延迟加载
<?php
namespace app\common\service;
use think\Container;
class LazyService
{
public function init()
{
$container = Container::getInstance();
// 延迟到需要时才实例化
$container->bind('heavyService', function() {
return new HeavyService(); // 懒加载
});
}
}
常见问题与解决方案
1 循环依赖
<?php
// 错误的循环依赖
class A {
public function __construct(B $b) {}
}
class B {
public function __construct(A $a) {} // 循环依赖
}
// 解决方案1:使用setter注入
class A {
public function setB(B $b) {
$this->b = $b;
}
}
// 解决方案2:使用容器方法
app()->bind(A::class, function() {
$a = new A();
$a->setB(app()->make(B::class));
return $a;
});
2 可选依赖
<?php
use think\Container;
class OptionalDependency
{
public function handle()
{
$container = Container::getInstance();
// 检查依赖是否存在
if ($container->has('optionalService')) {
$service = $container->make('optionalService');
}
// 或者设置默认值
$service = $container->make('optionalService', [
'default' => new DefaultService()
]);
}
}
最佳实践
- 接口绑定:总是使用接口绑定,便于替换和测试
- 构造函数注入:首选构造函数注入,确保依赖完整
- 缓存容器实例:适当使用单例减少资源消耗
- 依赖抽象:依赖抽象接口而不是具体实现
- 合理使用门面:门面提供简洁的静态调用但不会过度耦合
通过合理使用ThinkPHP的依赖注入容器,可以让你的项目更易于测试、维护和扩展。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播