Laravel 13 服务容器详解

摘要

Laravel 的服务容器是管理类依赖和执行依赖注入的强大工具。本文将深入讲解 Laravel 13 的服务容器,包括:

  • 服务绑定与解析
  • 依赖注入
  • 接口绑定
  • 上下文绑定
  • 实战案例与最佳实践

本文适合希望掌握服务容器的 Laravel 开发者。

1. 基本概念

1.1 什么是服务容器

服务容器是一个用于管理类依赖和执行依赖注入的工具。它可以帮助你:

  • 管理类依赖
  • 自动解析依赖
  • 绑定接口到实现
  • 管理单例

1.2 获取容器实例

1
2
3
4
use Illuminate\Container\Container;

$container = app();
$container = Container::getInstance();

2. 服务绑定

2.1 简单绑定

1
2
3
4
5
use App\Services\PaymentService;

app()->bind(PaymentService::class, function ($app) {
return new PaymentService();
});

2.2 单例绑定

1
2
3
app()->singleton(PaymentService::class, function ($app) {
return new PaymentService();
});

2.3 实例绑定

1
2
$service = new PaymentService();
app()->instance(PaymentService::class, $service);

2.4 绑定原始值

1
2
3
app()->when('App\Http\Controllers\UserController')
->needs('$apiKey')
->give(env('API_KEY'));

3. 服务解析

3.1 使用 make 方法

1
$service = app()->make(PaymentService::class);

3.2 使用 resolve 方法

1
$service = resolve(PaymentService::class);

3.3 使用 app 辅助函数

1
$service = app(PaymentService::class);

3.4 自动注入

1
2
3
4
5
6
7
8
9
use App\Services\PaymentService;

class OrderController extends Controller
{
public function store(PaymentService $payment)
{
// 自动注入
}
}

4. 接口绑定

4.1 定义接口

1
2
3
4
5
6
7
8
<?php

namespace App\Contracts;

interface PaymentInterface
{
public function process(float $amount): bool;
}

4.2 实现接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

namespace App\Services;

use App\Contracts\PaymentInterface;

class StripePayment implements PaymentInterface
{
public function process(float $amount): bool
{
// Stripe 支付处理
return true;
}
}

4.3 绑定接口到实现

1
2
3
4
5
6
7
8
// app/Providers/AppServiceProvider.php
use App\Contracts\PaymentInterface;
use App\Services\StripePayment;

public function register(): void
{
$this->app->bind(PaymentInterface::class, StripePayment::class);
}

4.4 使用接口

1
2
3
4
5
6
7
8
9
use App\Contracts\PaymentInterface;

class OrderController extends Controller
{
public function store(PaymentInterface $payment)
{
$payment->process(100.00);
}
}

5. 上下文绑定

5.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
use App\Contracts\PaymentInterface;
use App\Services\StripePayment;
use App\Services\PayPalPayment;

app()->when(OrderController::class)
->needs(PaymentInterface::class)
->give(StripePayment::class);

app()->when(SubscriptionController::class)
->needs(PaymentInterface::class)
->give(PayPalPayment::class);

5.2 闭包绑定

1
2
3
4
5
app()->when(OrderController::class)
->needs(PaymentInterface::class)
->give(function ($app) {
return new StripePayment(config('services.stripe'));
});

6. 标签绑定

6.1 定义标签

1
2
3
4
app()->bind('report.csv', CsvReporter::class);
app()->bind('report.pdf', PdfReporter::class);

app()->tag(['report.csv', 'report.pdf'], 'reports');

6.2 解析标签

1
2
3
4
5
$reports = app()->tagged('reports');

foreach ($reports as $report) {
$report->generate();
}

7. 实战案例

7.1 支付服务绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Contracts\PaymentInterface;
use App\Services\StripePayment;
use App\Services\PayPalPayment;

class PaymentServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->bind(PaymentInterface::class, function ($app) {
$provider = config('payment.default');

return match ($provider) {
'stripe' => new StripePayment(config('services.stripe')),
'paypal' => new PayPalPayment(config('services.paypal')),
default => throw new \Exception('Invalid payment provider'),
};
});
}
}

7.2 仓储模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Contracts\UserRepositoryInterface;
use App\Repositories\EloquentUserRepository;

class RepositoryServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->bind(UserRepositoryInterface::class, EloquentUserRepository::class);
}
}

8. 最佳实践

8.1 使用接口

1
2
3
4
5
// 推荐:依赖接口
public function __construct(PaymentInterface $payment) {}

// 不推荐:依赖具体实现
public function __construct(StripePayment $payment) {}

8.2 在服务提供者中绑定

1
2
3
4
5
6
7
8
// 推荐:在服务提供者中绑定
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->bind(Service::class, Implementation::class);
}
}

9. 总结

Laravel 的服务容器提供了强大的依赖注入能力:

  1. 服务绑定:灵活的绑定方式
  2. 自动解析:自动注入依赖
  3. 接口绑定:解耦接口与实现
  4. 上下文绑定:按需注入不同实现

参考资料