Laravel 13 服务提供者完全指南
服务提供者是 Laravel 应用的核心引导机制,负责注册服务容器绑定和配置应用的各种服务。本文将深入探讨 Laravel 13 中服务提供者的最佳实践和高级用法。
服务提供者基础
创建服务提供者
1
| php artisan make:provider PaymentServiceProvider
|
生成的服务提供者结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class PaymentServiceProvider extends ServiceProvider { public function register(): void { }
public function boot(): void { } }
|
注册与引导的区别
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
| class PaymentServiceProvider extends ServiceProvider { public function register(): void { $this->app->singleton(PaymentGatewayInterface::class, function ($app) { return new StripeGateway( config('services.stripe.secret') ); });
$this->app->bind(PaymentCalculator::class, function ($app) { return new PaymentCalculator( $app->make(TaxService::class) ); }); }
public function boot(): void { View::composer('payment.*', PaymentViewComposer::class); Gate::policy(Order::class, OrderPolicy::class); Route::model('order', Order::class); } }
|
注册服务绑定
单例绑定
1 2 3 4 5 6 7 8 9 10 11 12 13
| public function register(): void { $this->app->singleton(LoggerService::class, function ($app) { return new LoggerService( $app->make('log'), config('logging.channels.custom') ); });
$this->app->singleton('payment', function ($app) { return new PaymentManager($app); }); }
|
绑定接口到实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public function register(): void { $this->app->bind( RepositoryInterface::class, EloquentRepository::class );
$this->app->bind( CacheInterface::class, RedisCache::class );
$this->app->bind( QueueInterface::class, RedisQueue::class ); }
|
上下文绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| use App\Contracts\LoggerInterface; use App\Services\DatabaseLogger; use App\Services\FileLogger;
public function register(): void { $this->app->when(OrderController::class) ->needs(LoggerInterface::class) ->give(DatabaseLogger::class);
$this->app->when(PaymentController::class) ->needs(LoggerInterface::class) ->give(FileLogger::class);
$this->app->when(ReportService::class) ->needs('$reportType') ->give(config('reports.default_type')); }
|
标记服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public function register(): void { $this->app->singleton(EmailHandler::class); $this->app->singleton(SmsHandler::class); $this->app->singleton(PushHandler::class);
$this->app->tag([ EmailHandler::class, SmsHandler::class, PushHandler::class, ], 'notification.handlers'); }
public function boot(): void { $handlers = $this->app->tagged('notification.handlers'); foreach ($handlers as $handler) { $this->notificationManager->register($handler); } }
|
延迟加载提供者
创建延迟提供者
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\Providers;
use Illuminate\Support\ServiceProvider; use App\Services\HeavyService;
class HeavyServiceProvider extends ServiceProvider { protected bool $defer = true;
public function register(): void { $this->app->singleton(HeavyService::class, function ($app) { return new HeavyService(); }); }
public function provides(): array { return [HeavyService::class]; } }
|
条件加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class OptionalServiceProvider extends ServiceProvider { protected bool $defer = true;
public function register(): void { if (class_exists('SomePackage\Service')) { $this->app->singleton('some.service', function ($app) { return new \SomePackage\Service(); }); } }
public function provides(): array { return ['some.service']; } }
|
配置发布
发布配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public function boot(): void { $this->publishes([ __DIR__ . '/../../config/payment.php' => config_path('payment.php'), ], 'config');
$this->publishes([ __DIR__ . '/../../database/migrations/' => database_path('migrations'), ], 'migrations');
$this->publishes([ __DIR__ . '/../../resources/views/' => resource_path('views/vendor/payment'), ], 'views'); }
|
合并配置
1 2 3 4 5 6 7
| public function register(): void { $this->mergeConfigFrom( __DIR__ . '/../../config/payment.php', 'payment' ); }
|
发布组
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public function boot(): void { $this->publishes([ __DIR__ . '/../../config/payment.php' => config_path('payment.php'), ], 'payment-config');
$this->publishes([ __DIR__ . '/../../resources/views/' => resource_path('views/vendor/payment'), ], 'payment-views');
$this->publishes([ __DIR__ . '/../../public/' => public_path('vendor/payment'), ], 'payment-assets'); }
|
命令注册
注册 Artisan 命令
1 2 3 4 5 6 7 8 9 10
| public function boot(): void { if ($this->app->runningInConsole()) { $this->commands([ ProcessPaymentCommand::class, GenerateReportCommand::class, CleanupExpiredTokensCommand::class, ]); } }
|
计划任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| use Illuminate\Support\Facades\Schedule;
public function boot(): void { Schedule::command('payments:process') ->everyMinute() ->withoutOverlapping();
Schedule::command('reports:generate --daily') ->dailyAt('02:00') ->onOneServer();
Schedule::job(new CleanupJob()) ->hourly() ->graceTime(5); }
|
视图与路由注册
加载视图
1 2 3 4 5 6 7 8 9 10 11 12
| public function boot(): void { $this->loadViewsFrom( __DIR__ . '/../../resources/views', 'payment' );
$this->loadViewComponentsAs('payment', [ 'card' => PaymentCardComponent::class, 'form' => PaymentFormComponent::class, ]); }
|
加载路由
1 2 3 4 5
| public function boot(): void { $this->loadRoutesFrom(__DIR__ . '/../../routes/web.php'); $this->loadRoutesFrom(__DIR__ . '/../../routes/api.php'); }
|
加载迁移
1 2 3 4
| public function boot(): void { $this->loadMigrationsFrom(__DIR__ . '/../../database/migrations'); }
|
加载翻译
1 2 3 4 5 6 7
| public function boot(): void { $this->loadTranslationsFrom( __DIR__ . '/../../resources/lang', 'payment' ); }
|
高级用法
工厂模式绑定
1 2 3 4 5 6 7 8 9 10
| public function register(): void { $this->app->singleton(PaymentFactory::class, function ($app) { return new PaymentFactory([ 'stripe' => fn() => $app->make(StripeGateway::class), 'paypal' => fn() => $app->make(PayPalGateway::class), 'alipay' => fn() => $app->make(AlipayGateway::class), ]); }); }
|
装饰器模式
1 2 3 4 5 6
| public function register(): void { $this->app->extend(RepositoryInterface::class, function ($repository, $app) { return new CachedRepository($repository, $app->make(Cache::class)); }); }
|
解析回调
1 2 3 4 5 6 7 8 9 10 11 12
| public function register(): void { $this->app->resolving(RepositoryInterface::class, function ($repo, $app) { $repo->setLogger($app->make('log')); });
$this->app->resolving(function ($object, $app) { if (method_exists($object, 'setContainer')) { $object->setContainer($app); } }); }
|
服务提供者最佳实践
单一职责
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
| class PaymentServiceProvider extends ServiceProvider { public function register(): void { $this->registerGateways(); $this->registerCalculator(); $this->registerValidator(); }
protected function registerGateways(): void { $this->app->singleton(StripeGateway::class, function ($app) { return new StripeGateway(config('services.stripe')); }); }
protected function registerCalculator(): void { $this->app->singleton(PaymentCalculator::class); }
protected function registerValidator(): void { $this->app->singleton(PaymentValidator::class); } }
|
配置验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public function boot(): void { if (config('payment.enabled')) { $this->validateConfiguration(); } }
protected function validateConfiguration(): void { $required = ['payment.gateway', 'payment.currency']; foreach ($required as $key) { if (empty(config($key))) { throw new \RuntimeException("Missing required config: {$key}"); } } }
|
条件注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public function register(): void { if (!$this->app->configurationIsCached()) { $this->mergeConfigFrom( __DIR__ . '/../../config/payment.php', 'payment' ); } }
public function boot(): void { if ($this->app->runningInConsole()) { $this->commands([PaymentCommand::class]); }
if (!$this->app->routesAreCached()) { $this->loadRoutesFrom(__DIR__ . '/../../routes/api.php'); } }
|
测试服务提供者
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 28 29 30 31
| <?php
namespace Tests\Unit\Providers;
use Tests\TestCase; use App\Providers\PaymentServiceProvider; use App\Contracts\PaymentGatewayInterface; use App\Services\StripeGateway;
class PaymentServiceProviderTest extends TestCase { protected function getPackageProviders($app): array { return [PaymentServiceProvider::class]; }
public function test_it_binds_payment_gateway(): void { $gateway = $this->app->make(PaymentGatewayInterface::class); $this->assertInstanceOf(StripeGateway::class, $gateway); }
public function test_it_registers_singleton(): void { $gateway1 = $this->app->make(PaymentGatewayInterface::class); $gateway2 = $this->app->make(PaymentGatewayInterface::class); $this->assertSame($gateway1, $gateway2); } }
|
总结
Laravel 13 的服务提供者提供了强大的服务注册和引导机制。通过合理使用服务提供者,可以实现:
- 清晰的服务绑定和依赖注入
- 模块化的应用架构
- 延迟加载提升性能
- 可测试的代码结构
- 可复用的功能包
掌握服务提供者的使用是成为 Laravel 高级开发者的必经之路。