Service Container یا سرویس کانتینر در معماری نرم‌افزار مسئول ساخت آبجکت‌ها و رفع وابستگی‌های آن‌هاست. این مفهوم را نباید با کانتینر اشتباه گرفت. سرویس کانتینر با Dependency Injection و وارونگی کنترل ارتباط دارد و فقط مختص لاراول نیست، هرچند در لاراول یکی از بخش‌های اصلی فریم‌ورک است.

جایگاه آن در لاراول

در لاراول، کنترلر، Job و Listener می‌توانند کلاس‌های وابسته را از طریق Constructor Injection دریافت کنند. اگر کلاس به Interface وابسته باشد، کانتینر باید بداند کدام پیاده‌سازی را بسازد.

// app/Providers/AppServiceProvider.php
namespace App\Providers;

use App\Contracts\PaymentGateway;
use App\Services\StripeGateway;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind(PaymentGateway::class, StripeGateway::class);
        $this->app->singleton(ExchangeRateClient::class, fn () => new ExchangeRateClient());
    }
}

Bindingها عموماً در register() سرویس پرووایدر مثل AppServiceProvider نوشته می‌شوند. boot() برای کارهایی است که پس از ثبت سرویس‌ها اجرا می‌شوند و محل پیش‌فرض Binding نیست.

final class CheckoutController
{
    public function __construct(private PaymentGateway $gateway) {}

    public function charge(Order $order)
    {
        return $this->gateway->charge($order->total);
    }
}

چرخه عمر سرویس‌ها

روشرفتارمثال
bindنمونه جدید هنگام Resolveسرویس Stateless
singletonنمونه مشترک در طول عمر کانتینرکلاینت با تنظیمات ثابت
scopedنمونه مشترک در یک چرخه درخواست یا JobContext وابسته به درخواست

در فریم‌ورک‌های دیگر

پلتفرمراهکار
SymfonyService Container با Autowiring و پیکربندی services.yaml
ASP.NET Coreثبت سرویس با AddTransient، AddScoped و AddSingleton
Pythonتزریق دستی یا کتابخانه‌های Dependency Injector
GoComposition Root دستی یا ابزارهایی مانند Wire و Fx
// ASP.NET Core - Program.cs
builder.Services.AddScoped<IPaymentGateway, StripeGateway>();
builder.Services.AddSingleton<IClock, SystemClock>();
class CheckoutService:
    def __init__(self, gateway):
        self.gateway = gateway
service = CheckoutService(gateway=StripeGateway())

نکته طراحی

وقتی هر کلاس خودش کانتینر را برای گرفتن سرویس صدا می‌زند، خطر Service Locator و وابستگی پنهان وجود دارد. تزریق سازنده معمولاً شفاف‌تر است. راهبرد singleton در کانتینر به معنای اجرای تمام جزئیات دیزاین پترن سینگلتون نیست.

اصطلاحات مرتبط: تزریق وابستگی، وارونگی کنترل، اتصال خودکار وابستگی‌ها، دیزاین پترن سینگلتون، سرویس پرووایدر، فساد، سرویس کانتینر.