در این مقاله به آموزش استفادهی یکی از بهترین امکانات لاراول یعنی View Composer میپردازیم.
فرض کنید میخواهید تعداد زیادی از دادههای database را در صفحات مختلف سایت به کاربر نمایش دهید. سادهترین راه این است که در Controller دادهها را از Model بگیریم و به View ارسال کنیم. این کار تا زمانی که تعداد صفحات سایت کم باشد، تقریبا راهی معقول است. اما زمانی که سایت ما گسترش یابد، با مشکلاتی روبرو میشویم که به یک راه جایگزین نیاز پیدا میکنیم. این راه همان استفاده از View Composer است که در ادامه برای درک بهتر تفاوتها ابتدا راه معمولی را میگوییم، سپس آن را با View Composer مقایسه میکنیم. همچنین برای تفهیم بیشتر View Composer در لاراول مطالب یک پروژهی کوچک که میخواهد نام چند ماشین را نمایش دهد، پیادهسازی میکنیم.
روشی که ما در این آموزش به آن میپردازیم. ابتدا ساخت route، سپس controller و بعد از آن view است.
برای ساخت یک route در آدرس routes/web.php بهصورت زیر عمل میکنیم.
<?php
use Illuminate\Support\Facades\Route;
Route::get('cars','CarsController@index');
توسط دستور زیر یک Controller بهنام CarsController را ایجاد میکنیم.
$ php artisan make:controller CarsController
همان طور که مشاهده میکنید، برای نمایش دادهها route به CarsController میرود و تابع index را میخواند. پس تابع index را در CarsController ایجاد میکنیم و نام تمام ماشینها که از قبل در database ایجاد کردیم را از Model میگیریم و به یک View ارسال میکنیم.
<?php
namespace App\Http\Controllers;
use App\Cars;
use Illuminate\Http\Request;
class CarsController extends Controller
{
public function index()
{
$cars=Cars::all();
return view('cars.index',compact('cars'));
}
}
توجه کنید که حتما model خود را در بالا use کرده باشید.
اگر به تابع index در Controller توجه کرده باشید، میبینید که cars به یک View بهنام cars.index توسط تابع compact ارسال میشود. پس در این مرحله به ساخت View میپردازیم.
برای ساخت View ابتدا پوشهای بهنام cars در resources/views میسازیم. سپس فایل blade بهنام index را بهصورت زیر ایجاد میکنیم.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Cars</title>
</head>
<body>
<ul>
@foreach($cars as $car)
<li>{{ $car->name }}</li>
@endforeach
</ul>
</body>
</html>
حال در صفحهی سایتمان نام تمام ماشينها به صورت زیر نمايش داده میشود، که این همان راه معمولی و همیشگی است.
همانطور که مشاهده کردید، ما فقط برای یک صفحه از سایت یعنی صفحهی cars/ نیاز به ساخت Controller و سپس View داریم. فرض کنید که سایت ما دارای ۲۰ صفحه است که در تمام آن صفحات باید نام ماشینها، بهطور مثال در یک صفحه بهترتیب قیمت، در صفحهی دیگر بهترتیب سال تولید و در صفحات مختلف به ترتیبهای دیگری نمایش داده شود. در این صورت ساخت حداقل یک Controller برای هر کدام از آنها دیگر بهترین راه نیست و View Composer بهترین جایگزین است.
برای آشنایی با View Composer ابتدا میخواهیم یاد بگیریم که چگونه میتوانیم دادهها را به جای چند Controller تنها در یک قسمت وارد کنیم تا تمام Viewها به آن دسترسی داشته باشند.
برای اینکار به app/Providers/AppServiceProvider.php بروید و در تابع boot دستور زیر را وارد کنید.
<?php
namespace App\Providers;
use App\Cars;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
View::share('cars', Cars::orderBy('name')->get());
}
public function register()
{
//
}
}
ما از کلاس View، متد share را فراخوانی کردیم که پارامتر اول آن نام متغیر یعنی cars$ و پارامتر دوم مقدار cars$ است. (توجه کنید که از علامت $ در پارامترها استفاده نکنید.)
حال اگر در CarsController خط زیر و مقدار compact را پاک کنید و به صفحهی سایت بروید، مشاهده میکنید که تمامی دادهها مثل قبل، البته بهترتیب نام وجود دارند.
وقتی که یک متغیر را بهصورت بالا در AppServiceProvider و بهصورت Global تعریف میکنیم. بهطور خودکار این متغیر بهتمام Viewها چه بخواهیم، چه نخواهیم ارسال میشود و این کار database را بیهوده اشغال میکند.
View Composer مانند روش بالاست با این تفاوت که میتوانیم تعیین کنیم که متغیرمان به کدام Viewها ارسال شود.
<?php
namespace App\Providers;
use App\Cars;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
// Option 2
View::composer(['cars.index','cars.buy'], function($view)
{
$view->with('cars', Cars::orderBy('name')->get())
});
}
public function register()
{
//
}
}
ما از کلاس View، متد composer را فراخوانی کردیم که پارامتر اول آن صفحاتی که میخواهیم متغیر به آن ارسال شود و پارامتر دوم یک تابع callback است که مانند View::share عمل میکند و میتوانید همان اطلاعاتی که در View::share وارد کردید در with هم وارد کنید.
همچنین اگر میخواهید بهطور مثال متغیر به تمام Viewهای درون یک پوشه ارسال شود کافی است بهجای نام یک View علامت * را بهصورت زیر بگذارید.
View::composer(['cars.*'], function($view)
{
$view->with('cars', Cars::orderBy('name')->get())
});
حال اگر بهطور مثال بخواهیم که دادهها در یک صفحه بهترتیب نام، در صفحهای دیگر بهترتیب قیمت، و در هر صفحه به شکل خاصی مرتب شوند میتوانیم در app/Http یک پوشه بهنام View بسازیم و در آن پوشهای بهنام Composers ایجاد کنیم. بعد از ایجاد پوشهی Compossers در آن یک Class بهنام CarsComposer بسازید و درون CarsComposer کد زیر را وارد کنید :
<?php
namespace App\Http\View\Composers;
use App\Cars;
use Illuminate\View\View;
class CarsComposser
{
public function compose(View $view)
{
$view->with('cars', Cars::all());
}
}
همان دستوراتی که در تابع callback هنگام استفاده از View::composer وارد کردیم را در تابع compose کلاس بالا تعریف میکنیم. سپس به AppServiceProvider رفته و View::composer را بهصورت زیر تغییر میدهیم :
<?php
namespace App\Providers;
use App\Cars;
use App\Http\View\Composers\CarsComposser;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
//Option 3
View::composer(['cars.index','cars.buy'],CarsComposser::class);
}
public function register()
{
//
}
}
همچنین امكان دارد چندین View مختلف، در چندین پوشهی مختلف قرار داشته باشد. بهطور مثال فرض کنید که شما ۱۰ پوشه که در هر پوشه ۵ View قرار دارد را دارید. در این صورت وارد کردن Viewها کاری تقریبا زمانبر است. پس بهتر است از راه جایگزین استفاده کنید. بدین منظور قسمتهایی از View که دارای متغیر cars میباشد یعنی:
@foreach($cars as $car)
<li>{{ $car->name }}</li>
@endforeach
را به پوشهای مانند پوشهی partials میبریم و در view خود آن را include میکنیم.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Cars</title>
</head>
<body>
<ul>
@include('partials.list')
</ul>
</body>
</html>
سپس appServiceProvider را از
public function boot()
{
//Option 3
View::composer(['cars.index','cars.buy'],CarsComposser::class);
}
به
public function boot()
{
//Option 3
View::composer('partials.*',CarsComposser::class);
}
تغییر میدهیم.
جمعبندی:
در این مقاله سعی ما از ابتدا بر این بود، که مفاهيم را هر چه بهتر و در قالب یک پروژهی کوچک، همراه با مقایسه نسبت به روشهای دیگر به شما آموزش بدهیم. حال شما میتوانید از این قابلیت بزرگ لاراول در پروژههای خود همانگونه که میخواهید استفاده کنید. در صورت داشتن هرگونه سوال یا تجربهای در این زمینه، آن را در قسمت نظرات با ما به اشتراک بگذارید.
اگر به یادگیری بیشتر لاراول علاقه داری میتونی در دوره آموزش لاراول کاربردی (بسته پروژه محور) شرکت کنی، این دوره شامل ۱۲ پروژه کاربردی و پر استفاده در دنیای واقعی است، که تمامی پروژهها به صورت کامل برنامه نویسی خواهند شد، تا دانشجو بتواند با روند ایجاد و تکمیل پروژه به صورت کامل آشنا شود.
موفق باشید