بخش اول - سرویس کانتینر (قسمت دوم)
Contextual Binding (وابسته به موقعیت)
وقتی یک کلاس یا اینترفیس در یک زمینه (context) خاص نیاز به یک وابستگی (dependency) داره، از کدوم پیادهسازی (implementation) استفاده بشه. این ویژگی بهویژه زمانی مفیده که چند کلاس به یک اینترفیس نیاز دارن، اما هرکدوم باید پیادهسازی متفاوتی از اون اینترفیس رو دریافت کنن.
فرض کن دو کلاس داریم که هرکدوم به
LoggerInterface نیاز دارن:interface LoggerInterface {
public function log(string $message);
}
class FileLogger implements LoggerInterface {
public function log(string $message) {
}
}
class DatabaseLogger implements LoggerInterface {
public function log(string $message) {
}
}حالا میخواهیم برای هر کلاس پیادهسازی متفاوتی از
LoggerInterface تزریق کنیم:$this->app->when(OrderService::class)
->needs(LoggerInterface::class)
->give(FileLogger::class);
$this->app->when(UserService::class)
->needs(LoggerInterface::class)
->give(DatabaseLogger::class);
با این تنظیمات:
در
OrderService، کلاس FileLogger تزریق میشه.در
UserService، کلاس DatabaseLogger تزریق میشه.Binding Primitives
گاهی اوقات ممکنه کلاسی نیاز به تزریق مقادیر سادهای مثل اعداد، رشتهها یا آرایهها داشته باشه. در این مواقع، میتونیم با استفاده از Contextual Binding، این مقادیر رو بهصورت دقیق برای هر کلاس یا متد مشخص کنیم.
فرض کن یک کلاس
OrderProcessor داریم که به یک مقدار حداکثر تعداد سفارش نیاز داره:class OrderProcessor {
public function __construct(
protected int $maxOrders
) {}
public function process() {
}
}برای تزریق مقدار
maxOrders، میتونیم از needs() و give() استفاده کنیم:$this->app->when(OrderProcessor::class)
->needs('$maxOrders')
->give(100);
با این کار، هنگام ساخت نمونهای از
OrderProcessor، مقدار 100 بهعنوان maxOrders به سازنده تزریق میشه.Binding Typed Variadics
میتونیم متدهایی با پارامترهای متغیر (variadic) و تایپشده داشته باشیم. این ویژگی به ما این امکان رو میده که وابستگیهایی با تعداد و نوع مشخص رو بهصورت دقیق تزریق کنیم.
فرض کن یک کلاس
ReportGenerator داریم که به تعدادی فیلتر نیاز داره:class ReportGenerator {
public function __construct(
protected FilterInterface ...$filters
) {}
public function generate() {
}
}برای تزریق فیلترها، میتونیم از
needs() و give() استفاده کنیم:$this->app->when(ReportGenerator::class)
->needs(FilterInterface::class)
->give(function ($app) {
return [
new DateFilter(),
new StatusFilter(),
];
});
با این کار، هنگام ساخت نمونهای از
ReportGenerator، آرایهای از فیلترها بهعنوان وابستگیها تزریق میشه.متدهای مرتبط با Contextual Binding
1- متد when
این متد مشخص میکنه که binding در چه کلاسی اعمال بشه.
2- متد needs
با این متد مشخص میکنیم که کدوم وابستگی نیاز به تزریق داره.
3- متد give
با این متد پیادهسازی مورد نظر رو برای وابستگی مشخص میکنیم.
4- متد giveConfig
یک متد راحت برای تزریق مقادیر تنظیماتی به کلاسهاست، بهویژه زمانی که کلاس نیاز به مقادیر ساده (primitive) داره. درواقع نسخهی مخصوص برای
give() هست که با config() همخوانی داره.$this->app->when(PaymentGateway::class)
->needs('$apiKey')
->giveConfig('services.stripe.key');
5- متد giveTagged
برای تزریق تمام instanceهای مرتبط با یک tag به کلاسها یا متدها استفاده میشه. این زمانی مفیده که یک کلاس نیاز به مجموعهای از وابستگیها (مثلاً چندین سرویس، middleware، فیلتر و…) داره.
$this->app->tag([DateFilter::class, StatusFilter::class], 'filters');
$this->app->when(ReportGenerator::class)
->needs('$filters')
->giveTagged('filters');
تمام instanceهای تگ شده با
'filters' رو به $filters تزریق میکنه.نکته: درمورد تگها در قسمت بعدی توضیح کامل داده میشود.
در قسمتهای بعدی با سایر Injectionها آشنا خواهیم شد.
#laravel #لاراول #فصل_۷
@AmirhDeveloper
.