پوریا سیفی
پوریا سیفی
خواندن ۳ دقیقه·۳ سال پیش

بررسی Facades در لاراول

خب تو این مقاله میخوایم ببینیم اصلا فساد چیه؟ و قراره چه مشکلی رو برای ما حل بکنه!

اگه با فریم ورک لاراول کار کرده باشید حتما میدونید که یکی از مفاهیم مهم و کلیدی در لاراول، فساد ها هستند. به طور کلی فساد ها این امکان رو فراهم میکنند که خیلی سریع و راحت از سرویس کانتینر یه کلاس هایی رو بیرون بیاریم و استفاده بکنیم.


اگه احساس میکنید مفهموم سرویس کانتینر براتون مبهم هست، ابتدا لازمه این ابهام رو برطرف بکنید. پیشنهاد میکنم مقاله قبلی من در مورد سرویس کانتینر لاراول رو مطالعه کنید.

ابتدای کار چند مورد از فساد ها رو مرور کنیم :

Log::info('info text'); DB::table('users')->get(); Route::get('/'); Cache::get('key');

احتمالا خیلی با این موارد سر و کار داشتید اما تا حالا براتون سوال شده که ما چرا انقد از این حالت استاتیک (یعنی :: ) تو فراخوانی کلاس ها استفاده میکنیم؟ آیا همه این توابع واقعا به صورت استاتیک فراخوانی میشن؟؟

برای جواب دادن به این سوال مهم باید ببینیم درون فساد ها واقعا چه اتفاقی داره میفته. خب اولین جمله داکیومنت لاراول در مورد فساد ها اینه :

Facades provide a "static" interface to classes that are available in the application's IoC container
این جمله میگه که فساد ها یه بستری فراهم میکنن که ما استاتیک طوری به کلاس های مختلف موجود در سرویس کانتینر دسترسی داشته باشیم.

حالا سوال اصلی اینه که چرا از طریق متد استاتیک فراخوانی میشن؟

در جواب باید بگم که همونطور که درسته این فساد ها شبیه فراخوانی متد های استاتیک هستند ولی این فقط ظاهر ماجراست...

اگه یه نگاهی به مسیر

vendors / laravel/ framework / src/ illuminate / support / Facades

بندازید میبینید که همه خوبای لارول اینجا جمع شدن :)

همه این کلاس ها از vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php ارث بری میکنن و فقط یک متد getFacaseAccessor دارن.

حالا اتفاقی که پشت پرده میفته اینه که لاراول با استفاده این فایل ها و سینتکس استاتیک (همون ::) میاد از یه سری کلاس نمونه میسازه و اونو تو کل اپلیکیشن در اختیار ما قرار میده (اشاره به سرویس کانتینر).

حالا چرا استاتیک ؟ صرفا جهت راحتی و تمیز بودن و قشنگی!
Facades are just fancy ways of pulling things from the container
مگه میشه یه سری متد به ظاهر استاتیک بنویسی ولی تو واقعیت استاتیک نباشن؟ بله!

به عنوان مثال برای ثبت لاگ ما به این صورت عمل میکنیم :

Log::info('info text');

این یعنی اینکه سرویس کانتینر لطفا برو فایل Logger.php رو پیدا کن و ازش نمونه بساز بعد متد info رو برام اجرا کن. ضمنا ممکنه بازم بخوام لاگ بگیرم پس حواست باشه دفعه بعدی دیگه نمونه سازی نکنی (singleton) پس همین نمونه رو برام برگردون.

حالا سرویس کانتینر از کجا فهمید که فایل Logger.php رو پیدا کنه؟ این همون کاریه که متد getFacaseAccessor به همراه LogServiceProvider انجام میده. اگه این قسمت براتون مبهمه احتمالا با سرویس کانتینر ها آشنا نیستید. پیشنهاد میکنم مقاله سرویس کانتینر رو مطالعه کنید.

تصویر زیر همون متد info رو نشون میده که خیالتون راحت باشه هیچ خبری از متد استاتیک نیست.

حالا چرا فساد این کار رو میکنه؟ چند دلیل برای این کار وجود داره . مهم ترینش اینه که اینجوری ما هر بار مجبور نیستیم تو قسمت های مختلف اپلیکیشن از کلاس های پر کاربرد نمونه سازی بکنیم و حتما میدونید که منظور از ساختن نمونه صرفا یه new کردن ساده نیست . ممکنه سازنده ها کلی منطق پیچیده داشته باشن. از بررسی درایور ها گرفته تا شرایط تست پذیری و کلی مسائل دیگه...

یه جورایی لاراول اینجا از دیزاین پترن فساد هم استفاده کرده. “فساد” به معنی نمایه خارجی یا بیرونی هست و میشه گفت کارش اینه که پیچیدگی ها جزییات اضافی داخل یه سیستم رو پنهان کنه.



خب حالا فهمیدیم که فساد لاراول فراتر از دیزاین پترن فساد هست و به نظر من خیلی نباید این دو تا رو با هم قاطی کرد.


حالا اگه این سوال ذهنتون رو درگیر کرده که لاراول چطوری با سینتکس استاتیک پشت پرده نمونه سازی میکنه بیاید یه مقدار در مورد توابع استاتیک تو PHP صحبت کنیم. همونطور که میدونید برای اینکه به متغیر ها و توابع استاتیک موجود در یک کلاس دسترسی پیدا کنیم ، لازم نیست از اون کلاس شی بسازیم. به کلاس زیر دقت کنید :

<?php class Log { public static function info() { echo &quotinfo&quot   } }

خب اگه بخوایم واقعا به شکل استاتیک تابع info رو فراخوانی کنیم به این صورت عمل میکنیم

Log::info();

حالا فرض کنید کلا تابع info تو کلاس Log وجود نداشته باشه و ما بخوایم فراخوانی ش کنیم. چه اتفاقی میفته؟

خب معلومه با خطا (method not found) مواجه میشیم :)

حالا بیاید ببینیم قبل از اینکه به خطا بخوریم آیا میتونیم خطا رو هندل بکنیم یا نه.

احتمالا با متدهای مجیک در PHP آشنا باشید. مهم ترینش همون متدهای constructor کلاس ها هستند. اما مجیک فانکشن مورد نظر ما تو این مقاله callStatic__ هست. به کد زیر دقت کنید :

public static function __callStatic($name, $args){ return 'هرچی دلم خواست'; }

در واقع اگه این فانکشن تو کلاس ما وجود داشته باشه قبل از اینکه اون متد اصلا وجود خارجی داشته باشه و PHP بخواد بره به صورت استاتیک پیداش کنه این مجیک فانکشن اجرا میشه. بنابراین ما میتونیم همونجا هر مقداری دوست داشتیم براش برگردونیم. و اینجا همون جایی هست که لارول کارای مربوط به فساد رو انجام میده. مثلا از کلاس gh' نمونه میسازه ، درایور لاگ رو چک میکنه و ...

و دقیقا معادل تعریفی که برای پترن فساد داشتیم ، پیچیدگی های اضافی رو از دید ما پنهان میکنه.

استفاده از فساد ، مزایای دیگه ای مثل تست پذیری بهتر اپلیکیشن هم فراهم میکنه. در واقع میتونیم بفهمیم تو یه درخواست، آیا یک کلاس فراخوانی شده یا خیر؟ چنبار فراخوانی و با چه شرایطی فراخوانی شده و ...

امیدوارم از این مقاله استفاده کرده باشید .







فساد لاراولlaravel facadefacadelaravelلاراول
شاید از این پست‌ها خوشتان بیاید