Laravel 13 服务容器进阶
服务容器是 Laravel 的核心,提供了强大的依赖注入和服务管理能力。本文将深入探讨 Laravel 13 服务容器的高级用法。
服务容器基础
绑定服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| use App\Services\PaymentService; use App\Contracts\PaymentGateway;
app()->bind(PaymentService::class, function ($app) { return new PaymentService(); });
app()->singleton(PaymentService::class, function ($app) { return new PaymentService(config('payment')); });
$service = new PaymentService(); app()->instance(PaymentService::class, $service);
|
解析服务
1 2 3 4 5 6 7 8 9 10
| use App\Services\PaymentService;
$service = app(PaymentService::class);
$service = resolve(PaymentService::class);
$service = app()->make(PaymentService::class);
|
绑定类型
简单绑定
1 2 3 4 5 6 7 8
| app()->bind('service', function ($app) { return new Service(); });
$service1 = app('service'); $service2 = app('service');
|
单例绑定
1 2 3 4 5 6 7 8
| app()->singleton('service', function ($app) { return new Service(); });
$service1 = app('service'); $service2 = app('service');
|
作用域单例
1 2 3 4 5
| app()->scoped('service', function ($app) { return new Service(); });
|
实例绑定
1 2
| $service = new Service(); app()->instance('service', $service);
|
接口绑定
接口到实现
1 2 3 4
| use App\Contracts\PaymentGateway; use App\Services\StripeGateway;
app()->bind(PaymentGateway::class, StripeGateway::class);
|
条件绑定
1 2 3 4 5 6 7 8 9 10 11
| use App\Contracts\PaymentGateway; use App\Services\StripeGateway; use App\Services\PaypalGateway;
app()->bind(PaymentGateway::class, function ($app) { if (config('payment.provider') === 'stripe') { return new StripeGateway(); } return new PaypalGateway(); });
|
上下文绑定
when 方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| use App\Contracts\PaymentGateway; use App\Services\StripeGateway; use App\Services\PaypalGateway; use App\Controllers\OrderController; use App\Controllers\SubscriptionController;
app()->when(OrderController::class) ->needs(PaymentGateway::class) ->give(StripeGateway::class);
app()->when(SubscriptionController::class) ->needs(PaymentGateway::class) ->give(PaypalGateway::class);
|
给定值
1 2 3
| app()->when(OrderController::class) ->needs('$paymentProvider') ->give('stripe');
|
给定闭包
1 2 3 4 5
| app()->when(OrderController::class) ->needs(PaymentGateway::class) ->give(function ($app) { return new StripeGateway(config('stripe')); });
|
标签绑定
定义标签
1 2 3 4
| app()->tag([ StripeGateway::class, PaypalGateway::class, ], 'payment-gateways');
|
解析标签
1 2 3 4 5
| $gateways = app()->tagged('payment-gateways');
foreach ($gateways as $gateway) { $gateway->process(); }
|
自动解析
构造函数注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php
namespace App\Services;
use App\Contracts\PaymentGateway;
class OrderService { public function __construct( protected PaymentGateway $gateway ) {} }
$orderService = app(OrderService::class);
|
方法注入
1 2 3 4 5 6 7 8 9 10 11 12 13
| <?php
namespace App\Http\Controllers;
use App\Services\OrderService;
class OrderController extends Controller { public function store(OrderService $service) { $service->process(); } }
|
服务提供者
创建服务提供者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider; use App\Contracts\PaymentGateway; use App\Services\StripeGateway;
class PaymentServiceProvider extends ServiceProvider { public function register(): void { $this->app->bind(PaymentGateway::class, StripeGateway::class); $this->app->singleton('payment', function ($app) { return new PaymentService($app->make(PaymentGateway::class)); }); }
public function boot(): void { $this->publishes([ __DIR__.'/../../config/payment.php' => config_path('payment.php'), ]); } }
|
注册服务提供者
1 2 3 4 5
| 'providers' => [ App\Providers\AppServiceProvider::class, App\Providers\PaymentServiceProvider::class, ],
|
延迟提供者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class PaymentServiceProvider extends ServiceProvider { protected $defer = true;
public function register(): void { $this->app->singleton('payment', function ($app) { return new PaymentService(); }); }
public function provides(): array { return ['payment']; } }
|
解析高级用法
带参数解析
1 2
| $service = app()->makeWith(Service::class, ['param' => 'value']); $service = app()->make(Service::class, ['param' => 'value']);
|
容器调用
1 2 3 4 5 6 7
| use App\Services\OrderService;
$result = app()->call([OrderService::class, 'process']);
$result = app()->call(function (OrderService $service) { return $service->process(); });
|
带参数调用
1 2 3 4 5 6 7
| $result = app()->call([OrderService::class, 'process'], [ 'orderId' => 123, ]);
$result = app()->call(function (OrderService $service, $orderId) { return $service->process($orderId); }, ['orderId' => 123]);
|
容器事件
解析事件
1 2 3 4 5 6 7
| app()->resolving(function ($object, $app) { });
app()->resolving(PaymentService::class, function ($service, $app) { });
|
afterResolving
1 2 3
| app()->afterResolving(function ($object, $app) { });
|
容器扩展
extend 方法
1 2 3 4
| app()->extend(Service::class, function ($service, $app) { $service->setLogger($app->make(LoggerInterface::class)); return $service; });
|
依赖注入
控制器注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?php
namespace App\Http\Controllers;
use App\Services\UserService;
class UserController extends Controller { public function __construct( protected UserService $userService ) {}
public function index() { return $this->userService->getAll(); } }
|
中间件注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?php
namespace App\Http\Middleware;
use Closure; use App\Services\AnalyticsService;
class TrackPageView { public function __construct( protected AnalyticsService $analytics ) {}
public function handle($request, Closure $next) { $this->analytics->track($request); return $next($request); } }
|
命令注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <?php
namespace App\Console\Commands;
use Illuminate\Console\Command; use App\Services\ReportService;
class GenerateReport extends Command { protected $signature = 'report:generate';
public function __construct( protected ReportService $reportService ) { parent::__construct(); }
public function handle(): int { $this->reportService->generate(); return 0; } }
|
测试服务容器
模拟绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| use App\Services\PaymentService;
public function test_payment_service(): void { $mock = $this->mock(PaymentService::class, function ($mock) { $mock->shouldReceive('process')->once()->andReturn(true); });
$this->app->instance(PaymentService::class, $mock);
$response = $this->postJson('/api/orders');
$response->assertStatus(201); }
|
交换实例
1 2 3 4 5 6 7 8 9 10 11
| use App\Services\PaymentService;
public function test_with_fake_service(): void { $fake = new FakePaymentService(); $this->app->instance(PaymentService::class, $fake);
$response = $this->postJson('/api/orders');
$this->assertTrue($fake->wasCalled()); }
|
最佳实践
1. 使用接口绑定
1 2 3 4 5
| app()->bind(PaymentGatewayInterface::class, StripeGateway::class);
app()->bind('payment', StripeGateway::class);
|
2. 使用服务提供者
1 2 3 4 5 6 7 8 9 10 11
| class PaymentServiceProvider extends ServiceProvider { public function register(): void { $this->app->bind(PaymentGateway::class, StripeGateway::class); } }
app()->bind(PaymentGateway::class, StripeGateway::class);
|
3. 使用类型提示
1 2 3 4 5 6 7 8 9 10
| public function __construct( protected PaymentService $paymentService ) {}
public function __construct() { $this->paymentService = app(PaymentService::class); }
|
总结
Laravel 13 的服务容器提供了强大而灵活的依赖注入能力。通过合理使用绑定、上下文绑定、标签和服务提供者,可以构建出松耦合、可测试的应用程序。记住使用接口绑定来实现依赖反转原则,在服务提供者中注册服务,并通过构造函数注入来获取依赖。服务容器是 Laravel 的核心,理解它的工作原理对于构建高质量的 Laravel 应用至关重要。