لاراول یکی از فریم ورک های MVC که با زبان PHP نوشته شده و به همین خاطر ، وقتی از اون استفاده می کنیم، مدل ها و کنترل ها، کدهای زیادی دارند، و این غیر منطقی نیست چونکه برای انجام کارهای پیچیده و عملیات های مختلف به این لایهها نیاز داریم.
تا اینجای کار مشکلی نیست.
مشکل وقتی بوجود میاد که ما در یکی از لایه ها، کدها و مسئولیت زیادی داشته باشیم. این میتونه به کدهای اصلی ما آسیب بزنه.
حجیم شدن هرچیزی همیشه مخالف الگو است، خرد کردن نگرانی ها، به نگهداری و آزمایش بهتر آن کمک می کند.
اما وقتی می گیم: « Skinny Controllers, Fat Models » ، کنترلر های لاغر ، مدل های چاق ، منظور اینه که مدل فقط یک کلاس نیست بلکه یک لایه است. داشتن مدل خفن هم همیشه خوب نیست.
اجازه بدید باهم بررسی کنیم که چطوری کدهای خودمون در یک ساختار مناسب در لاراول توسعه بدیم.
خب، وظیفه اصلی کنترلر چی هست؟
کنترلر ها تقاضا ها ( ریکوئست ها ) رو دریافت می کنند و پاسخ ( ریسپانس ) های مناسب رو بر میگردونند.
به طور کلی مسئولیت های زیر به عهده کنترلر هاست:
پس منطق های برنامه (business logic ) چی میشه؟ اینها باید در لایه مدل پیاده سازی بشه
کنترلر نباید کاری انجام بده بلکه باید کارها رو به کسی که میتونه انجام بده واگذار کنه.
اونها باید ساده ، لاغر ، کوتاه ، مختصر و با مسئولیت کمتری باشند.
اگر از این قانون پیروی کنیم ، از یکی از anti-pattern های تکراری جلوگیری می کنیم: کنترلر چاق.
توجه: شما میتونید حداکثر تعداد خطوطی رو که میخواهید در یک کنترلر داشته باشید رو برای خودتون تعریف کنید. به عنوان مثال ، 10 خط میتونه در بیشتر موارد کافی باشد.
و چرا داشتن کنترلرهای چاق بد است؟ اساساً به دو دلیل:
البته لایه مدل میتونه از کلاسهای مختلفی تشکیل بشه و نه فقط یک کلاس.
باشه، الان کنترلر ما خیلی تمیزتر از قبل شده، اما یه مدل داریم با یه عالمه کد که نگهداریش مشکل شده.
ما باید مدل خودمون رو به یک ساختار تقسیم کنیم. این ساختار میتونه درون این لایه های کد باشه:
برای تأیید سناریوهای پیچیده تر ، می تونیم از FormRequest استفاده کنیم.
برای ایجاد کلاس FormRequest کافیه دستور زیر رو اجرا کنید.
php artisan make:request StoreBlogPost
کلاس ایجاد شده در مسیر app/Http/Requests
در دسترس هست.
و در آخر میتونیم چند قانون رو به متد rules
اضافه کنیم:
/** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]; }
حالا ببینیم تایید میشه یا نه:
// Retrieve the validated input data... $validated = $request->validated();
این لایه راهی برای متمرکز کردن کدها است. با استفاده از service provider میتونیم کدها را به کنترلر تزریق کنیم. ما میتونیم منطق های چاق خودمون رو ، که روی داده های ورودی اثر میگذارند ، اینجا بزاریم. همچنین ، میتونیم اونها رو با یکی از دو رویکرد زیر توسعه بدیم:
یا اینکه: سرویسهایی هستند که همه منطق ها رو میتونه در بر بگیره.
اونها همه وابستگی هایی که تزریق شده اند رو دارند و وقتی اونها رو فراخوانی میکنیم همه عملیات ها اجرا خواهند شد. بیشتر از این چیزی نیاز نیست.
برای تعاملات با پایگاه داده ، می تونیم از الگوی طراحی Repository استفاده کنیم.
این ایده میگه که : مدل ها رو از کنترلر ها جدا کنید و نام های خوانا، برای کوئری ها پیچیده بزارید.
اگر نیاز به اجرای منطقی داشته باشیم که در نتیجه اجرای منطقی دیگه، لازم میشه و همچنین منطق اول وابسته به جواب منطق دوم نباشه از رویداد استفاده میکنیم.
و اگه بشه این منطق رو از چند جا فراخوانی کنیم، رویداد بهترین گزینه است.
مثال : ارسال ایمیل خوش آمد گویی به کاربر بعد از ثبت نام
در مثال بالا ثبت نام وابسته به نتیجه ارسال ایمیل نیست.
انتشار لاراول 5.5 ، Responsable Interface رو به همراه داشت که اجازه تبدیل آبجکت ها، در یک پاسخ (Response) به HTTP رو میده.
میتونید هر پارامتری رو به متد سازنده ( constructor ) پاس بدید و تمام منطق مورد نیاز خودتون رو در متد ()toResponse پیاده سازی کنید، این متد خودش بقیه کارها رو انجام میده. با این روش لایه مدل ما نیاز نیست نگران فرمت مورد نیاز کلاینت باشه. ما میتونیم این وظیفه رو به لایه Responsable واگذار کنیم.
همچنین در استفاده مجدد از این کد به ما کمک میکنه و ما میتونیم یک فرمت کلی و یکسان در خروجی داشته باشیم درحالی که هر عملیات میتونه از Responsable مربوط به خودش استفاده کنه.
یک وظیفه یا تسکی که در بخش نمایش داده ها (فرانت یا view) خیلی بهش نیاز داریم، قالب بندی داده هاست. مثل فرمت تاریخ یا تبدیل نرخ ارز و ...
با View Composers میتونید این کارها رو راحت کنید.
اینها callbacks یا کلاسهایی هستند که موقع نمایش view فراخوانی میشوند و این به ما کمک میکنه که منطق مورد نیاز در این بخش رو در مکانی واحد سازماندهی کنیم.
آیا موافق نیستید که کنترلرها لاغر و مدل های چاق بسیار تمیزتر و ساده تر شدند؟ همچنین کد بیشتر قابل نگهداری و استفاده است؟
ما منطق تجاری کدهای خودمون رو در لایه مدل قرار دادیم و به این ترتیب از کدهای تکراری جلوگیری کردیم.
مطمئناً، همه مثالهایی که مطرح شد در همه ی موارد راه حل نیست، اما قاعده کلی اینه که:
اگر بتوان چیزی را از کنترلر حذف کرد، استفاده مجدد و تست راحت تر است.
ممنون که وقتتون رو برای مطالعه این مطلب صرف کردید.
اگه نکته و یا نظری دارید از شنیدنش خوشحال میشم.
سپاس