موفرو الخدمات
موفرو الخدمات
موفرو الخدمات هم المكان المركزي لجميع عمليات بدء تشغيل تطبيق Laravel. هم مسؤولون عن ربط الخدمات في الحاوية، وتسجيل مستمعي الأحداث، والبرامج الوسيطة، والمسارات، ومهام الإعداد الأخرى. فهم موفري الخدمات هو مفتاح فهم كيفية تكوين وبدء تشغيل تطبيقات Laravel.
ما هي موفرو الخدمات؟
موفرو الخدمات هم فئات تسجل وتبدأ مكونات تطبيق Laravel الخاص بك. كل تطبيق Laravel لديه موفر خدمة واحد على الأقل (AppServiceProvider)، ويتضمن الإطار نفسه العديد من الموفرين للخدمات الأساسية.
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
// ربط الخدمات في الحاوية
// يعمل قبل أي طريقة boot()
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
// تنفيذ بدء التشغيل بعد التسجيل
// يعمل بعد تسجيل جميع الموفرين
}
}
register() الأشياء فقط في حاوية الخدمات. يتم استدعاء طريقة boot() بعد تسجيل جميع الموفرين، لذا يمكنك استخدام الخدمات الأخرى بأمان في boot().
طريقة Register
طريقة register هي المكان الذي تربط فيه الخدمات والواجهات والتبعيات الأخرى في حاوية الخدمات:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Services\PaymentGateway;
use App\Services\StripePaymentGateway;
use App\Contracts\ReportGeneratorInterface;
use App\Services\PdfReportGenerator;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
// ربط بسيط
$this->app->bind(PaymentGateway::class, function ($app) {
return new StripePaymentGateway(
config('services.stripe.key')
);
});
// ربط Singleton
$this->app->singleton(
ReportGeneratorInterface::class,
PdfReportGenerator::class
);
// تسجيل ملف التكوين
$this->mergeConfigFrom(
__DIR__.'/../config/mypackage.php',
'mypackage'
);
// التسجيل الشرطي بناءً على البيئة
if ($this->app->environment('local')) {
$this->app->register(DebugServiceProvider::class);
}
}
}
طريقة Boot
تعمل طريقة boot بعد تسجيل جميع موفري الخدمات، مما يجعل من الآمن استخدام الخدمات الأخرى:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Blade;
use App\Models\User;
class AppServiceProvider extends ServiceProvider
{
public function boot(): void
{
// مشاركة البيانات مع جميع العروض
View::share('appName', config('app.name'));
// تعريف بوابات التفويض
Gate::define('update-post', function (User $user, $post) {
return $user->id === $post->user_id;
});
// تسجيل توجيهات Blade
Blade::directive('datetime', function ($expression) {
return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
});
// تسجيل مراقبي النموذج
User::observe(UserObserver::class);
// نشر أصول الحزمة
$this->publishes([
__DIR__.'/../resources/views' => resource_path('views/vendor/mypackage'),
], 'mypackage-views');
// تسجيل الماكرو
\Illuminate\Support\Str::macro('titleSnake', function ($value) {
return \Illuminate\Support\Str::title(
str_replace('_', ' ', $value)
);
});
}
}
حقن التبعيات في طريقة Boot
يمكنك التلميح إلى أنواع التبعيات في طريقة boot، وستقوم الحاوية بحقنها تلقائياً:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Contracts\View\Factory as ViewFactory;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
//
}
/**
* التبعيات محقونة تلقائياً
*/
public function boot(
ResponseFactory $response,
ViewFactory $view
): void {
// استخدام التبعيات المحقونة
$view->composer('*', function ($view) {
$view->with('currentYear', date('Y'));
});
// إضافة ماكرو استجابة مخصص
$response->macro('caps', function ($value) use ($response) {
return $response->make(strtoupper($value));
});
}
}
إنشاء موفري خدمات مخصصين
عند بناء تطبيقات أكبر، من الممارسات الجيدة إنشاء موفري خدمات مخصصين لمكونات مختلفة:
// إنشاء موفر خدمات جديد
php artisan make:provider PaymentServiceProvider
// app/Providers/PaymentServiceProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Services\Payment\StripeGateway;
use App\Services\Payment\PayPalGateway;
use App\Contracts\PaymentGatewayInterface;
class PaymentServiceProvider extends ServiceProvider
{
public function register(): void
{
// ربط بوابة الدفع بناءً على التكوين
$this->app->singleton(
PaymentGatewayInterface::class,
function ($app) {
$driver = config('payment.default');
return match($driver) {
'stripe' => new StripeGateway(
config('payment.stripe.key')
),
'paypal' => new PayPalGateway(
config('payment.paypal.client_id')
),
default => throw new \Exception("Unsupported payment driver: {$driver}")
};
}
);
}
public function boot(): void
{
// نشر التكوين
$this->publishes([
__DIR__.'/../config/payment.php' => config_path('payment.php'),
], 'payment-config');
}
}
// التسجيل في مصفوفة موفري config/app.php
'providers' => [
// ... موفرون آخرون
App\Providers\PaymentServiceProvider::class,
],
الموفرون المؤجلون
يتم تحميل الموفرين المؤجلين فقط عندما تكون خدماتهم مطلوبة فعلاً، مما يحسن أداء التطبيق:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Support\DeferrableProvider;
use App\Services\ReportGenerator;
class ReportServiceProvider extends ServiceProvider implements DeferrableProvider
{
public function register(): void
{
$this->app->singleton(ReportGenerator::class, function ($app) {
return new ReportGenerator(
$app->make('db'),
$app->make('config')
);
});
}
/**
* Get the services provided by the provider.
*
* @return array<int, string>
*/
public function provides(): array
{
// قائمة بجميع الخدمات التي يقدمها هذا الموفر
return [
ReportGenerator::class,
];
}
}
// الفوائد:
// - يتم تحميل الموفر فقط عندما تكون ReportGenerator مطلوبة
// - يقلل وقت بدء التشغيل
// - يحسن الأداء للطلبات التي لا تحتاج إلى تقارير
نشر أصول الحزمة
تسمح موفرو الخدمات للحزم بنشر ملفات التكوين والعروض والهجرات والأصول الأخرى:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class MyPackageServiceProvider extends ServiceProvider
{
public function boot(): void
{
// نشر التكوين
$this->publishes([
__DIR__.'/../config/mypackage.php' => config_path('mypackage.php'),
], 'mypackage-config');
// نشر العروض
$this->publishes([
__DIR__.'/../resources/views' => resource_path('views/vendor/mypackage'),
], 'mypackage-views');
// نشر الهجرات
$this->publishes([
__DIR__.'/../database/migrations' => database_path('migrations'),
], 'mypackage-migrations');
// نشر الأصول (CSS، JS، الصور)
$this->publishes([
__DIR__.'/../public' => public_path('vendor/mypackage'),
], 'mypackage-assets');
// نشر مجموعات أصول متعددة في وقت واحد
$this->publishes([
__DIR__.'/../config/mypackage.php' => config_path('mypackage.php'),
__DIR__.'/../resources/views' => resource_path('views/vendor/mypackage'),
], 'mypackage-all');
}
}
// المستخدمون ينشرون مع أوامر artisan:
php artisan vendor:publish --tag=mypackage-config
php artisan vendor:publish --tag=mypackage-views
php artisan vendor:publish --tag=mypackage-all
php artisan vendor:publish --provider="App\Providers\MyPackageServiceProvider"
تحميل موارد الحزمة
يمكن لموفري الخدمات تحميل العروض والترجمات والهجرات والمسارات من الحزم:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class MyPackageServiceProvider extends ServiceProvider
{
public function boot(): void
{
// تحميل عروض الحزمة
$this->loadViewsFrom(__DIR__.'/../resources/views', 'mypackage');
// تحميل ترجمات الحزمة
$this->loadTranslationsFrom(__DIR__.'/../lang', 'mypackage');
// تحميل هجرات الحزمة
$this->loadMigrationsFrom(__DIR__.'/../database/migrations');
// تحميل مسارات الحزمة
$this->loadRoutesFrom(__DIR__.'/../routes/web.php');
}
}
// استخدام الموارد المحملة:
// العروض: return view('mypackage::dashboard');
// الترجمات: __('mypackage::messages.welcome')
// الهجرات: تعمل تلقائياً مع php artisan migrate
// المسارات: مسجلة تلقائياً
الخلاصة
موفرو الخدمات هم حجر الزاوية في تكوين تطبيق Laravel:
- طريقة Register: ربط الخدمات في الحاوية فقط
- طريقة Boot: بدء تشغيل الخدمات والعروض والبوابات وما إلى ذلك بعد التسجيل
- حقن التبعيات: يمكن لطريقة boot التلميح إلى التبعيات
- موفرون مخصصون: تنظيم التطبيق من خلال إنشاء موفرين مخصصين
- موفرون مؤجلون: التحميل فقط عند الحاجة لأداء أفضل
- النشر: السماح للمستخدمين بتخصيص أصول الحزمة
- تحميل الموارد: جعل عروض الحزمة والترجمات والمسارات متاحة
في الدرس التالي، سنستكشف أوامر Artisan Console وكيفية إنشاء أدوات CLI مخصصة لتطبيق Laravel الخاص بك.