首页 > PHP > Laravel教程 契约(Contracts) 应用场景 示例代码

Laravel教程 契约(Contracts) 应用场景 示例代码

2025-02-27 14:09:17

Laravel 的 契约(Contracts) 是一组定义框架核心服务的接口(Interface)。它们规范了服务的公共方法,例如 Cache 契约规定了 get()put() 等方法。通过依赖这些接口而非具体实现,代码耦合度降低,灵活性和可测试性增强。

契约的核心作用

  1. 解耦代码:依赖接口而非具体类,轻松替换实现。
  2. 提高可测试性:通过 Mock 接口,方便单元测试。
  3. 框架灵活性:允许开发者自定义服务实现。

使用内置契约

示例1:在控制器中使用缓存契约

use Illuminate\Contracts\Cache\Factory as Cache;

class UserController extends Controller
{
    protected $cache;

    // 依赖注入 Cache 契约
    public function __construct(Cache $cache)
    {
        $this->cache = $cache;
    }

    public function showProfile($id)
    {
        // 通过契约调用缓存
        $user = $this->cache->get('user:'.$id, function () use ($id) {
            return User::findOrFail($id);
        });

        return view('profile', ['user' => $user]);
    }
}

示例2:使用日志契约

use Illuminate\Contracts\Logging\Log;

class OrderService
{
    protected $logger;

    public function __construct(Log $logger)
    {
        $this->logger = $logger;
    }

    public function processOrder($order)
    {
        try {
            // 处理订单逻辑...
        } catch (Exception $e) {
            $this->logger->error('订单处理失败', ['error' => $e->getMessage()]);
        }
    }
}

创建自定义契约

步骤1:定义契约接口

// app/Contracts/PaymentGateway.php
namespace App\Contracts;

interface PaymentGateway
{
    public function charge($amount, $token);
    public function refund($transactionId);
}

步骤2:实现接口

// app/Services/StripePaymentGateway.php
namespace App\Services;

use App\Contracts\PaymentGateway;

class StripePaymentGateway implements PaymentGateway
{
    public function charge($amount, $token)
    {
        // Stripe 支付逻辑
        return 'Charge successful with Stripe';
    }

    public function refund($transactionId)
    {
        // Stripe 退款逻辑
        return 'Refund processed via Stripe';
    }
}

步骤3:绑定契约到服务容器

// 在 AppServiceProvider 的 register 方法中
use App\Contracts\PaymentGateway;
use App\Services\StripePaymentGateway;

public function register()
{
    $this->app->bind(PaymentGateway::class, StripePaymentGateway::class);
}

步骤4:使用自定义契约

use App\Contracts\PaymentGateway;

class PaymentController extends Controller
{
    protected $paymentGateway;

    public function __construct(PaymentGateway $paymentGateway)
    {
        $this->paymentGateway = $paymentGateway;
    }

    public function processPayment(Request $request)
    {
        $result = $this->paymentGateway->charge(1000, $request->token);
        return response()->json(['message' => $result]);
    }
}

契约与服务容器

绑定方式

  • 简单绑定$this->app->bind(Contract::class, Implementation::class);
  • 单例绑定$this->app->singleton(Contract::class, Implementation::class);
  • 上下文绑定:根据使用场景指定不同实现

解析契约实例

$payment = app()->make(PaymentGateway::class);

实际应用场景

场景1:动态切换缓存驱动

// 在服务提供者中根据配置绑定
if (config('cache.driver') === 'redis') {
    $this->app->bind(CacheContract::class, RedisCache::class);
} else {
    $this->app->bind(CacheContract::class, FileCache::class);
}

场景2:多邮件服务商支持

interface EmailSender {
    public function send($to, $content);
}

// 实现类:MailgunSender, SendGridSender...
// 根据配置动态绑定

最佳实践

  1. 优先使用内置契约:如 CacheQueueMail 等
  2. 保持契约简洁:接口方法应聚焦单一职责
  3. 合理使用依赖注入:控制器、Job、中间件等均可注入
  4. 结合单元测试:Mock 契约验证业务逻辑

总结

 

使用 Ctrl+D 可将网站添加到书签
收藏网站
扫描二维码
关注早实习微信公众号
官方公众号
Top