سلام :)
توی این پست میخوام راجع به یک قابلیت توی لاراول صحبت کنم که باعث میشه کد تمیزتری داشته باشیم.
فرض کنید ما یه وبسایت خبری داریم که خبرهای مختلفی دارد.( ورزشی، اقتصادی، فرهنگی و ...).
خب پس باید یک table بنام categories داشته باشیم.
اگه بخواهیم این table را در جاهای مختلف برنامه لود کنیم باید در جاهای مختلف بنویسیم
$categories=Category::all();
مثلا توی یک view که میخواهیم خبری را منتشر کنیم، بخواهیم که category ها را هم در یک navbar نمایش دهد.
پس باید اینگونه بنویسیم
$categories=Category::all(); $post=Post::findOrFail($id); return view('post.show')->with('post',$post)->with('categories', $categories);
خب همونطور که میدونید طبق اصل اول solid هر متد باید برای انجام یک کار باشد ولی اینجا هم category رو میگیرم و هم post. در واقع در کلاس مربوط به Postها داریم Category میگیریم. مهمتر از اون اینه که اگر چند جای برنامه بخواهیم category ها را نمایش دهیم یک کد را چندین بار باید تکرار کنیم .
اینجاست که میتوانیم از این ویژگی خوب لاراول استفاده کنیم.
میتونیم بریم توی appServiceProvider. اما پیشنهاد من اینکه برای اینکه کدامون مجزا و تمیز باشه یک provider جدا درست کنیم.
php artisan make:provider ViewServiceProvider
یا هر اسم دیگه ای که دوست داریم بنویسیم.
و بعد کدهای مربوط به view composer را در متد Boot مینویسیم.
برای نوشتن کد میتوانیم به ۳ روش بنویسیم
روش اول :
View::share($key,$query);
خب key در واقع همون متغیر ما است که اینجا اسمش categories است و دومین آرگومان ما چیزی است که میخواهیم categories به ما نشان دهد.
پس در واقع کد ما میشود
View::share('categories ',Category::all() );
پس دیگه هرجایی توی برنامه میتونیم راحت از categories استفاده کنیم. اما این روش خیلی توصیه نمیشه
زیرا هر سری که داریم یک view را فراخوانی میکنیم این query اجرا میشود که اینکار منطقی نیست چون ما نیاز نداریم که در تمام view ها Categories داشته باشیم.
از متد share زمانی استفاده میکنیم که بخواهیم اطلاعاتی داشته باشیم که توی هر صفحه به نمایش گذاشته شود.
روش دوم:
از متد composer استفاده میکنیم.
View::composer([views],function ($view){ // });
توی این روش آرگمان اول اسم view یا viewهایی است که میخواهیم خروجی را در آنها نمایش دهیم. میتواند به صورت string باشد( اگر ۱ آیتم داریم) یا array( برای بیشتر از یکی)
فقط view هایی که مشخص کردیم به categories دسترسی دارند.
نکته: میتوانیم به جای اینکه تک تک اسم viewها را بنویسیم، از * یا مثلا .*.post$ استفاده کنیم. در این حالت تمام viewهایی که در directory بنام post هستند میتوانند به متغیر ما دسترسی داشته باشند.
آرگمان دوم هم یک callback function است.
View::composer([views],function ($view){ $view->with('categories', Category::all() ); });
و توی callback function اول اسم متغیر و بعد query مد نظرمون رو مینویسیم.
روش سوم :
توی این روش یه directoryتوی app درست میکنیم به نام view و بعد یک directory دیگر به نام Composer میکنیم.
یک کلاس بصورت دستی درست میکنیم. (command line برای درست کردنش نداریم و باید دستی درست بشه).
داخل این کلاس فقط یک متد داریم بنام compose با آرگمان ورودی view.
,و بعد دقیقا همان کدی که توی callback فانکشن روش قبل نوشتیم.
و بعد توی متد boot مینویسیم .
View::composer(['views'],CategoriesComposer::class);
نظر شخصی:
اگه تعداد view ها زیاد شود استفاده از روش دوم باعث شلوغی متد boot میشود پس بهتر است از روش سوم که کلاس مجزا دارد استفاده کنیم.
همین.
امیدوارم که این آموزش براتون مفید باشه :)