کنترل کننده ها
- معرفی
- کنترل کننده های پایه
- میان افزار کنترلر
- کنترل کننده های منابع
- تزریق وابستگی و کنترلرها
- حافظه پنهان مسیر
معرفی
به جای اینکه تمام منطق رسیدگی به درخواست خود را به عنوان Closures در فایل
های مسیر تعریف کنید، ممکن است بخواهید این رفتار را با استفاده از کلاس های Controller سازماندهی کنید.
کنترلرها می توانند منطق رسیدگی به درخواست مرتبط را در یک کلاس واحد گروه
بندی کنند.
کنترلرها در
app/Http/Controllers
دایرکتوری ذخیره می شوند.
کنترل کننده های پایه
تعریف کنترلرها
در زیر نمونه ای از یک کلاس کنترل کننده پایه آورده شده است.
توجه داشته باشید که کنترل کننده کلاس کنترل کننده پایه موجود در لاراول را
گسترش می دهد.
کلاس پایه چند روش آسان مانند
middleware
متد را ارائه می دهد که ممکن است برای اتصال میان افزار به اقدامات کنترل
کننده استفاده شود:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use App\User; class UserController extends Controller{ /** * Show the profile for the given user. * * @param int $id * @return View */ public function show($id) { return view('user.profile', ['user' => User::findOrFail($id)]); }}
شما می توانید مسیری را برای این عملکرد کنترلر تعریف کنید:
Route::get('user/{id}', 'UserController@show');
اکنون، زمانی که یک درخواست با URI مسیر مشخص شده مطابقت داشته باشد،
show
متد روی
UserController
کلاس اجرا خواهد شد.
پارامترهای مسیر نیز به متد ارسال خواهند شد.
کنترلرها نیازی به گسترش کلاس پایه ندارند . با این حال، به ویژگیهای راحتی مانند، و روشها دسترسی
middleware
نخواهیدvalidate
داشتdispatch
.
کنترلرها و فضاهای نام
توجه به این نکته بسیار مهم است که هنگام تعریف مسیر کنترلر، نیازی به تعیین
فضای نام کامل کنترلر نداشتیم.
از آنجایی که
RouteServiceProvider
فایلهای مسیر شما را در یک گروه مسیر که حاوی فضای نام است بارگیری میکند،
ما فقط بخشی از نام کلاس را که بعد از
App\Http\Controllers
بخشی از فضای نام قرار میگیرد، مشخص کردیم.
اگر میخواهید کنترلکنندههای خود را عمیقتر در
App\Http\Controllers
دایرکتوری قرار دهید، از نام کلاس خاص نسبت به
App\Http\Controllers
فضای نام ریشه استفاده کنید.
بنابراین، اگر کلاس کنترلر کامل شما
App\Http\Controllers\Photos\AdminController
, باید مسیرهایی را به کنترلر مانند زیر ثبت کنید:
Route::get('foo', 'Photos\AdminController@method');
کنترلرهای تک اقدام
اگر میخواهید کنترلکنندهای تعریف کنید که فقط یک عمل را انجام دهد،
میتوانید یک
__invoke
متد را روی کنترلکننده قرار دهید:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use App\User; class ShowProfile extends Controller{ /** * Show the profile for the given user. * * @param int $id * @return View */ public function __invoke($id) { return view('user.profile', ['user' => User::findOrFail($id)]); }}
هنگام ثبت مسیرها برای کنترلرهای تکی، نیازی به تعیین روش ندارید:
Route::get('user/{id}', 'ShowProfile');
--invokable
شما می توانید با استفاده از دستور Artisan
یک کنترل کننده فراخوانی ایجاد کنید
make:controller
:
php artisan make:controller ShowProfile --invokable
خرد کنترلر ممکن است با استفاده از انتشار خرد سفارشی شود
میان افزار کنترلر
میان افزار ممکن است به مسیرهای کنترل کننده در فایل های مسیر شما اختصاص داده شود:
Route::get('profile', 'UserController@show')->middleware('auth');
با این حال، تعیین میان افزار در سازنده کنترلر راحت تر است.
با استفاده
middleware
از روش سازنده کنترلر خود، می توانید به راحتی میان افزار را به اکشن کنترلر
اختصاص دهید.
حتی ممکن است میان افزار را فقط به روش های خاصی در کلاس کنترلر محدود کنید:
class UserController extends Controller{ /** * Instantiate a new controller instance. * * @return void */ public function __construct() { $this->middleware('auth'); $this->middleware('log')->only('index'); $this->middleware('subscribed')->except('store'); }}
کنترلرها همچنین به شما این امکان را می دهند که میان افزار را با استفاده از Closure ثبت کنید. این یک راه راحت برای تعریف یک میان افزار برای یک کنترل کننده بدون تعریف کل کلاس میان افزار فراهم می کند:
$this->middleware(function ($request, $next) { // ... return $next($request);});
میتوانید میانافزار را به زیرمجموعهای از اقدامات کنترلکننده اختصاص دهید. با این حال، ممکن است نشان دهنده بزرگ شدن کنترلر شما باشد. در عوض، کنترل کننده خود را به چندین کنترلر کوچکتر تقسیم کنید.
کنترل کننده های منابع
مسیریابی منابع لاراول مسیرهای معمولی "CRUD" را به یک کنترلر با یک خط کد
اختصاص می دهد.
برای مثال، ممکن است بخواهید یک کنترلکننده ایجاد کنید که تمام درخواستهای
HTTP برای "عکسهای" ذخیره شده توسط برنامه شما را مدیریت کند.
با استفاده از
make:controller
دستور Artisan، می توانیم به سرعت چنین کنترل کننده ای ایجاد کنیم:
php artisan make:controller PhotoController --resource
این دستور یک کنترلر در
app/Http/Controllers/PhotoController.php
.
کنترل کننده شامل یک روش برای هر یک از عملیات منابع موجود خواهد بود.
در مرحله بعد، می توانید یک مسیر پرمحتوا به کنترل کننده ثبت کنید:
Route::resource('photos', 'PhotoController');
این اعلان مسیر واحد، مسیرهای متعددی را برای انجام انواع اقدامات روی منبع ایجاد می کند. کنترلکننده ایجاد شده قبلاً روشهایی را برای هر یک از این اقدامات، از جمله یادداشتهایی که به شما از افعال HTTP و URIهایی که مدیریت میکنند، آگاه میکند، خواهد داشت.
شما می توانید با ارسال یک آرایه به
resources
متد، بسیاری از کنترل کننده های منبع را به طور همزمان ثبت کنید:
Route::resources([ 'photos' => 'PhotoController', 'posts' => 'PostController',]);
اقدامات انجام شده توسط کنترل کننده منابع
فعل | URI | عمل | نام مسیر |
---|---|---|---|
گرفتن | /photos |
فهرست مطالب | photos.index |
گرفتن | /photos/create |
ايجاد كردن | عکس. ایجاد |
پست | /photos |
فروشگاه | photos.store |
گرفتن | /photos/{photo} |
نشان می دهد | عکس.نمایش |
گرفتن | /photos/{photo}/edit |
ویرایش کنید | photos.edit |
PUT/PATCH | /photos/{photo} |
به روز رسانی | photos.update |
حذف | /photos/{photo} |
از بین رفتن | عکس. تخریب |
مشخص کردن مدل منبع
اگر از اتصال مدل مسیر استفاده میکنید و میخواهید که روشهای کنترلکننده
منبع، نمونهای از مدل را تایپ کنند، میتوانید
--model
هنگام تولید کنترلکننده از این گزینه استفاده کنید:
php artisan make:controller PhotoController --resource --model=Photo
روش های فرم جعل
از آنجایی که فرمهای HTML نمیتوانند، یا درخواست ایجاد
PUT
کنند
PATCH
،
DELETE
باید یک
_method
فیلد مخفی برای جعل این افعال HTTP اضافه کنید.
دستورالعمل
@method
Blade می تواند این فیلد را برای شما ایجاد کند:
<form action="/foo/bar" method="POST"> @method('PUT')</form>
مسیرهای منابع جزئی
هنگام اعلام مسیر منبع، میتوانید زیرمجموعهای از اقداماتی را که کنترلر باید انجام دهد، به جای مجموعه کامل اقدامات پیشفرض مشخص کنید:
Route::resource('photos', 'PhotoController')->only([ 'index', 'show']); Route::resource('photos', 'PhotoController')->except([ 'create', 'store', 'update', 'destroy']);
مسیرهای منبع API
هنگام اعلام مسیرهای منبعی که توسط APIها مصرف می شوند، معمولاً می خواهید
مسیرهایی را که الگوهای HTML را ارائه می دهند حذف
create
کنید
edit
.
برای راحتی، می توانید از
apiResource
روشی برای حذف خودکار این دو مسیر استفاده کنید:
Route::apiResource('photos', 'PhotoController');
شما می توانید با ارسال یک آرایه به متد، بسیاری از کنترل کننده های منبع
API را به طور همزمان ثبت کنید
apiResources
:
Route::apiResources([ 'photos' => 'PhotoController', 'posts' => 'PostController',]);
create
برای تولید سریع یک کنترلکننده منبع API که شامل یا
edit
متدها
نمیشود ،
--api
هنگام اجرای
make:controller
دستور از سوئیچ استفاده کنید:
php artisan make:controller API/PhotoController --api
منابع تو در تو
گاهی اوقات ممکن است لازم باشد مسیرهایی را برای یک منبع تودرتو تعریف کنید. به عنوان مثال، یک منبع عکس ممکن است چندین نظر داشته باشد که ممکن است به عکس پیوست شود. برای قرار دادن کنترلکنندههای منبع، از علامت نقطه در اعلان مسیر خود استفاده کنید:
Route::resource('photos.comments', 'PhotoCommentController');
این مسیر یک منبع تودرتو را ثبت می کند که ممکن است با URI هایی مانند زیر قابل دسترسی باشد:
/photos/{photo}/comments/{comment}
لانه سازی کم عمق
اغلب، داشتن شناسه والد و فرزند در یک URI کاملاً ضروری نیست، زیرا شناسه فرزند در حال حاضر یک شناسه منحصر به فرد است. هنگام استفاده از شناسه منحصربهفرد مانند کلیدهای اصلی افزایش خودکار برای شناسایی مدلهای خود در بخشهای URI، میتوانید از «تودرتوی سطحی» استفاده کنید:
Route::resource('photos.comments', 'CommentController')->shallow();
تعریف مسیر بالا مسیرهای زیر را تعریف می کند:
فعل | URI | عمل | نام مسیر |
---|---|---|---|
گرفتن | /photos/{photo}/comments |
فهرست مطالب | photos.comments.index |
گرفتن | /photos/{photo}/comments/create |
ايجاد كردن | عکس.نظرات.ایجاد |
پست | /photos/{photo}/comments |
فروشگاه | photos.comments.store |
گرفتن | /comments/{comment} |
نشان می دهد | نظرات.نمایش |
گرفتن | /comments/{comment}/edit |
ویرایش کنید | نظرات.ویرایش |
PUT/PATCH | /comments/{comment} |
به روز رسانی | نظرات.به روز رسانی |
حذف | /comments/{comment} |
از بین رفتن | نظرات.ویران کردن |
نامگذاری مسیرهای منابع
به طور پیش فرض، تمام اقدامات کنترل کننده منبع یک نام مسیر دارند.
با این حال، می توانید این نام ها را با ارسال یک
names
آرایه با گزینه های خود لغو کنید:
Route::resource('photos', 'PhotoController')->names([ 'create' => 'photos.build']);
نامگذاری پارامترهای مسیر منبع
به طور پیش فرض،
Route::resource
پارامترهای مسیر را برای مسیرهای منبع شما بر اساس نسخه "تکین" نام منبع
ایجاد می کند.
با استفاده از روش می توانید به راحتی این را بر اساس هر منبع لغو کنید
parameters
.
آرایه ارسال شده به
parameters
متد باید یک آرایه انجمنی از نام منابع و نام پارامترها باشد:
Route::resource('users', 'AdminUserController')->parameters([ 'users' => 'admin_user']);
مثال بالا URI های زیر را برای مسیر منبع تولید می کند
show
:
/users/{admin_user}
مسیرهای منابع محدوده
گاهی اوقات، هنگامی که به طور ضمنی چندین مدل Eloquent را در تعاریف مسیر منابع متصل میکنید، ممکن است بخواهید دامنه مدل Eloquent دوم را به گونهای تنظیم کنید که باید فرزند اولین مدل Eloquent باشد. به عنوان مثال، این وضعیت را در نظر بگیرید که یک پست وبلاگ را توسط یک کاربر خاص بازیابی می کند:
use App\Http\Controllers\PostsController; Route::resource('users.posts', PostsController::class)->scoped();
میتوانید با ارسال یک آرایه به
scoped
روش، کلیدهای مسیر پیشفرض مدل را لغو کنید:
use App\Http\Controllers\PostsController; Route::resource('users.posts', PostsController::class)->scoped([ 'post' => 'slug',]);
هنگام استفاده از یک اتصال ضمنی با کلید سفارشی به عنوان پارامتر مسیر
تودرتو، لاراول به طور خودکار محدوده پرس و جو را برای بازیابی مدل تودرتو توسط والد خود با استفاده از
قراردادها برای حدس زدن نام رابطه روی والد، بررسی می کند.
در این حالت، فرض می شود که
User
مدل دارای رابطه ای به نام
posts
(جمع نام پارامتر مسیر) است که می تواند برای بازیابی
Post
مدل استفاده شود.
بومی سازی URI های منبع
به طور پیش فرض،
Route::resource
URI های منبع را با استفاده از افعال انگلیسی ایجاد می کند.
اگر نیاز به بومی سازی افعال
create
و
edit
عمل دارید، می توانید از
Route::resourceVerbs
روش استفاده کنید.
این ممکن است در
boot
روش شما انجام شود
AppServiceProvider
:
use Illuminate\Support\Facades\Route; /** * Bootstrap any application services. * * @return void */public function boot(){ Route::resourceVerbs([ 'create' => 'crear', 'edit' => 'editar', ]);}
هنگامی که افعال سفارشی شدند، یک ثبت مسیر منبع مانند
Route::resource('fotos', 'PhotoController')
URI های زیر را تولید می کند:
/fotos/crear /fotos/{foto}/editar
تکمیل کنترل کننده های منابع
اگر نیاز به اضافه کردن مسیرهای اضافی به کنترلکننده منبع فراتر از مجموعه
پیشفرض مسیرهای منبع دارید، باید آن مسیرها را قبل از تماس خود با
Route::resource
;
در غیر این صورت، مسیرهای تعریف شده توسط
resource
روش ممکن است ناخواسته بر مسیرهای تکمیلی شما اولویت داشته باشند:
Route::get('photos/popular', 'PhotoController@method'); Route::resource('photos', 'PhotoController');
به یاد داشته باشید که کنترلرهای خود را متمرکز نگه دارید. اگر متوجه شدید که به طور معمول به روشهایی خارج از مجموعه اقدامات معمول منابع نیاز دارید، کنترل کننده خود را به دو کنترلر کوچکتر تقسیم کنید.
تزریق وابستگی و کنترلرها
تزریق سازنده
کانتینر سرویس لاراول برای حل همه کنترلرهای لاراول استفاده می شود. در نتیجه، میتوانید هر نوع وابستگی را که کنترلر شما ممکن است در سازنده خود به آن نیاز داشته باشد را تایپ کنید. وابستگی های اعلام شده به طور خودکار حل می شوند و به نمونه کنترلر تزریق می شوند:
<?php namespace App\Http\Controllers; use App\Repositories\UserRepository; class UserController extends Controller{ /** * The user repository instance. */ protected $users; /** * Create a new controller instance. * * @param UserRepository $users * @return void */ public function __construct(UserRepository $users) { $this->users = $users; }}
همچنین می توانید هر قرارداد لاراول را تایپ کنید . اگر ظرف می تواند آن را حل کند، می توانید آن را تایپ کنید. بسته به برنامه شما، تزریق وابستگی های شما به کنترلر ممکن است تست پذیری بهتری را ارائه دهد.
روش تزریق
علاوه بر تزریق سازنده، میتوانید وابستگیهای متدهای کنترلر خود را نیز
تایپ کنید.
یک مورد رایج برای تزریق روش، تزریق
Illuminate\Http\Request
نمونه به روشهای کنترلکننده است:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class UserController extends Controller{ /** * Store a new user. * * @param Request $request * @return Response */ public function store(Request $request) { $name = $request->name; // }}
اگر روش کنترلر شما نیز انتظار ورودی از پارامتر مسیر را دارد، آرگومان های مسیر خود را بعد از وابستگی های دیگر فهرست کنید. برای مثال، اگر مسیر شما به این صورت تعریف شده باشد:
Route::put('user/{id}', 'UserController@update');
همچنان می توانید با تعریف روش کنترلر خود به صورت زیر، پارامتر
را تایپ کنید
Illuminate\Http\Request
و به پارامتر خود دسترسی پیدا کنید :
id
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class UserController extends Controller{ /** * Update the given user. * * @param Request $request * @param string $id * @return Response */ public function update(Request $request, $id) { // }}
حافظه پنهان مسیر
مسیرهای مبتنی بر بسته شدن را نمی توان در حافظه پنهان ذخیره کرد. برای استفاده از کش مسیر، باید هر مسیر Closure را به کلاس های کنترلر تبدیل کنید.
اگر برنامه شما منحصراً از مسیرهای مبتنی بر کنترلر استفاده می کند، باید از
کش مسیر لاراول استفاده کنید.
استفاده از کش مسیر، مدت زمان ثبت تمام مسیرهای برنامه شما را به شدت کاهش
می دهد.
در برخی موارد، ثبت مسیر شما حتی ممکن است تا 100 برابر سریعتر باشد.
برای ایجاد کش مسیر، کافیست
route:cache
دستور Artisan را اجرا کنید:
php artisan route:cache
پس از اجرای این دستور، فایل routes ذخیره شده شما در هر درخواست بارگذاری
می شود.
به یاد داشته باشید، اگر مسیرهای جدیدی اضافه کنید، باید یک مسیر کش جدید
ایجاد کنید.
به همین دلیل، شما باید
route:cache
دستور را فقط در حین استقرار پروژه خود اجرا کنید.
می توانید از
route:clear
دستور برای پاک کردن کش مسیر استفاده کنید:
php artisan route:clear