بخش اول - سرویس کانتینر (قسمت سوم)
Contextual Attributes
این قابلیت امکان استفاده از PHP Attributes را در سازندهها و متدها فراهم میکند تا تزریق وابستگیها در Service Container به شکل سادهتر، شفافتر و قابل خواندنتری انجام شود.
این ویژگی در عمل جایگزین بسیاری از مواردی است که پیشتر تنها از طریق Contextual Binding (مانند when()->needs()->give()) امکانپذیر بود.
فرض کنید در یک کنترلر نیاز دارید از یک دیسک خاص برای ذخیرهسازی استفاده کنید. پیشتر لازم بود این موضوع را در Service Provider تعریف کنید، اما اکنون کافی است از Attribute استفاده نمایید:
use Illuminate\Container\Attributes\Storage;
use Illuminate\Contracts\Filesystem\Filesystem;
class PhotoController extends Controller
{
public function __construct(
#[Storage('local')] protected Filesystem $filesystem
) {}
}
در این مثال، لاراول بهطور خودکار دیسک با نام local را پیدا کرده و به متغیر $filesystem تزریق میکند.
لاراول چندین Attribute داخلی پرکاربرد ارائه کرده است، از جمله:
1- #[Storage('disk-name')]
برای تزریق یک دیسک ذخیرهسازی مشخص.
2- #[Config('config.key')]
برای تزریق مستقیم مقادیر پیکربندی.
3- #[DB('connection-name')]
برای تزریق یک اتصال پایگاهداده خاص.
4- #[Auth('guard-name')]
برای تزریق گارد احراز هویت مشخص.
5- #[Cache('store-name')]
برای تزریق یک cache store.
6- #[Log('channel')]
برای تزریق یک کانال لاگ.
7- #[RouteParameter('param')]
برای تزریق پارامترهای مسیر.
8- #[Tag('tag-name')]
برای تزریق مجموعهای از سرویسهای تَگشده.
9- #[CurrentUser]
برای تزریق مستقیم کاربر احراز هویتشدهٔ فعلی.
مثال:
Route::get('/user', function (#[CurrentUser] User $user) {
return $user;
})->middleware('auth');در این مثال، Attribute CurrentUser باعث میشود که نمونهای از مدل User که معادل کاربر احراز هویتشدهٔ جاری است، بدون هیچ کد اضافهای تزریق گردد.
تعریف Attributes سفارشی
در برخی پروژهها ممکن است نیاز به منطق خاصی داشته باشید. در این حالت میتوانید Attribute سفارشی خود را تعریف کنید.
برای ساخت یک Attribute سفارشی یک کلاس با annotation #[Attribute] تعریف کنید و رابط ContextualAttribute را پیادهسازی کنید.
namespace App\Attributes;
use Attribute;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Container\ContextualAttribute;
#[Attribute(Attribute::TARGET_PARAMETER)]
class AppConfig implements ContextualAttribute
{
public function __construct(
public string $key,
public mixed $default = null
) {}
public static function resolve(self $attribute, Container $container)
{
return $container->make('config')->get($attribute->key, $attribute->default);
}
}
نمونه استفاده:
public function __construct(
#[AppConfig('app.name')] protected string $appName
) {}
Tagging
در سرویس کانتینر، Tagging این امکان را فراهم میکند که چندین کلاس یا binding را تحت یک نام مشترک گروهبندی کنید و بعداً همه آنها را با یک فراخوانی ساده دریافت نمایید. این ویژگی بهویژه زمانی مفید است که چند پیادهسازی از یک interface یا کلاس وجود داشته باشد و بخواهید همه یا تعدادی از آنها را در یک زمان استفاده کنید.
$this->app->bind(SlackMessenger::class, function ($app) {
return new SlackMessenger(/* ... */);
});
$this->app->bind(TwilioMessenger::class, function ($app) {
return new TwilioMessenger(/* ... */);
});
$this->app->tag([SlackMessenger::class, TwilioMessenger::class], 'messengers');در این مثال، دو کلاس مربوط به پیامرسانی با تگ 'messengers' علامتگذاری میشوند.
در جایی از اپ که نیاز به اجرای عملیات روی همهی پیامرسانها دارید:
$messengers = $this->app->tagged('messengers');تمام instanceهای مربوط به تگ 'messengers' را برمیگرداند.
در قسمتهای بعدی با سایر Injectionها آشنا خواهیم شد.
#laravel #لاراول #فصل_۷
@AmirhDeveloper
.