2026-07-06 Abdelrhman Yasser
حاوية الخدمة وحقن التبعيات في Laravel
حاوية الخدمة وحقن التبعيات: قلب Laravel
مدة القراءة: 30 دقيقة
مقدمة
حاوية الخدمة (Service Container) في Laravel هي الجهاز العصبي المركزي للإطار — تدير تبعيات الكلاسات، وتؤدي حقن التبعيات (Dependency Injection)، وتتحكم في إنشاء الكائنات. فهم الحاوية ضروري لكتابة تطبيقات Laravel قابلة للاختبار والتوسع والصيانة.
ما هو حقن التبعيات؟
حقن التبعيات (DI) هو نمط تصميم حيث يتلقى الكلاس تبعياته من الخارج بدلاً من إنشائها داخلياً.
// ❌ بدون DI — تبعية صلبة
class UserController
{
private UserService $service;
public function __construct()
{
$this->service = new UserService(new MySQLUserRepository());
}
}
// ✅ مع DI — تُحقن التبعيات
class UserController
{
public function __construct(
private UserService $service
) {}
}
أنواع الربط (Binding)
ربط بسيط (bind) — كل مرة يعيد إنشاء
ربط مفرد (singleton) — يعيد نفس الكائن
ربط بنطاق (scoped) — نفس الكائن ضمن النطاق (مفيد مع Octane)
$this->app->bind(PaymentGateway::class, StripeGateway::class);
$this->app->singleton(HelpSpot\API::class, function ($app) {
return new HelpSpot\API($app->config->get('helpspot.api_key'));
});
ربط الواجهات بالتطبيقات
$this->app->bind(PaymentGateway::class, StripeGateway::class);
// تغيير مزود الدفع بتغيير سطر واحد
$this->app->bind(PaymentGateway::class, PayPalGateway::class);
الربط السياقي (Contextual Binding)
عندما تحتاج كلاسات مختلفة تطبيقات مختلفة لنفس الواجهة:
$this->app->when(PhotoController::class)
->needs(Filesystem::class)
->give(function () { return Storage::disk('local'); });
$this->app->when(VideoController::class)
->needs(Filesystem::class)
->give(function () { return Storage::disk('s3'); });
Service Providers
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->bind(PaymentGateway::class, StripeGateway::class);
}
public function boot(): void
{
// بعد تسجيل كل المزودين
}
}
Facades
الـ Facades توفر واجهة تشبه static للخدمات المسجلة في الحاوية:
Cache::get('key');
// يعادل:
$app->make('cache')->get('key');
أخطاء شائعة
- إفراط في التبعيات في الـ Constructor — يقسم المسؤوليات
- ربط كل شيء "فقط في حالة" — اربط الواجهات فقط
- استخدام
app()في القوالب — مرر البيانات من التحكم - نسيان استخدام الواجهات — يمنع التبديل السهل
أسئلة المقابلات
- ما الفرق بين
bindوsingleton؟ - كيف يعمل الربط السياقي ومتى تستخدمه؟
- اشرح
register()vsboot()في Service Providers. - كيف تعمل Facades تحت الغطاء؟