کنترل کننده ها
معرفی
به جای اینکه تمام منطق رسیدگی به درخواست خود را به عنوان بسته در فایل های مسیر خود تعریف کنید، ممکن است بخواهید این رفتار را با استفاده از کلاس های "کنترل کننده" سازماندهی کنید. کنترلرها می توانند منطق رسیدگی به درخواست مرتبط را در یک کلاس واحد گروه بندی کنند. به عنوان مثال، یک
UserController
کلاس ممکن است تمام درخواستهای دریافتی مربوط به کاربران، از جمله نمایش، ایجاد، بهروزرسانی و حذف کاربران را مدیریت کند. به طور پیش فرض، کنترلرها در
app/Http/Controllers
دایرکتوری ذخیره می شوند.
کنترل کننده های نوشتن
کنترل کننده های پایه
برای تولید سریع یک کنترلر جدید، می توانید
make:controller
دستور Artisan را اجرا کنید. بهطور پیشفرض، همه کنترلکنندههای برنامه شما در
app/Http/Controllers
دایرکتوری ذخیره میشوند:
php artisan make:controller UserController
بیایید نگاهی به نمونه ای از یک کنترل کننده اولیه بیندازیم. یک کنترلر ممکن است تعدادی روش عمومی داشته باشد که به درخواست های HTTP ورودی پاسخ دهد:
<?php namespace App\Http\Controllers; use App\Models\User;use Illuminate\View\View; class UserController extends Controller{ /** * Show the profile for a given user. */ public function show(string $id): View { return view('user.profile', [ 'user' => User::findOrFail($id) ]); }}
هنگامی که یک کلاس و متد کنترلر نوشتید، می توانید مسیری را برای متد کنترلر تعریف کنید:
use App\Http\Controllers\UserController; Route::get('/user/{id}', [UserController::class, 'show']);
هنگامی که یک درخواست ورودی با URI مسیر مشخص شده مطابقت دارد،
show
متد روی
App\Http\Controllers\UserController
کلاس فراخوانی می شود و پارامترهای مسیر به متد ارسال می شود.
کنترلرها نیازی به گسترش کلاس پایه ندارند . با این حال، گاهی اوقات گسترش یک کلاس کنترل کننده پایه که شامل روش هایی است که باید در همه کنترلرهای شما به اشتراک گذاشته شود، راحت است.
کنترلرهای تک اقدام
اگر یک اکشن کنترلر بسیار پیچیده باشد، ممکن است برای شما راحت باشد که یک کلاس کنترلر را به آن عمل اختصاص دهید. برای انجام این کار، می توانید یک
__invoke
روش واحد را در کنترلر تعریف کنید:
<?php namespace App\Http\Controllers; class ProvisionServer extends Controller{ /** * Provision a new web server. */ public function __invoke() { // ... }}
هنگام ثبت مسیرها برای کنترلرهای تکی، نیازی به تعیین روش کنترلر ندارید. در عوض، می توانید به سادگی نام کنترلر را به روتر ارسال کنید:
use App\Http\Controllers\ProvisionServer; Route::post('/server', ProvisionServer::class);
--invokable
شما می توانید با استفاده از دستور Artisan
یک کنترل کننده فراخوانی ایجاد کنید
make:controller
:
php artisan make:controller ProvisionServer --invokable
خرد کنترلر ممکن است با استفاده از انتشار خرد سفارشی شود .
میان افزار کنترلر
میان افزار ممکن است به مسیرهای کنترل کننده در فایل های مسیر شما اختصاص داده شود:
Route::get('profile', [UserController::class, 'show'])->middleware('auth');
یا، ممکن است برای شما راحت باشد که میان افزار را در کلاس کنترلر خود مشخص کنید. برای انجام این کار، کنترلر شما باید
HasMiddleware
اینترفیس را پیاده سازی کند، که دیکته می کند که کنترلر باید یک
middleware
متد استاتیک داشته باشد. از این روش، میتوانید آرایهای از میانافزار را برگردانید که باید برای اقدامات کنترلکننده اعمال شود:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use Illuminate\Routing\Controllers\HasMiddleware;use Illuminate\Routing\Controllers\Middleware; class UserController extends Controller implements HasMiddleware{ /** * Get the middleware that should be assigned to the controller. */ public static function middleware(): array { return [ 'auth', new Middleware('log', only: ['index']), new Middleware('subscribed', except: ['store']), ]; } // ...}
همچنین میتوانید میانافزار کنترلکننده را بهعنوان بستهشده تعریف کنید، که راهی مناسب برای تعریف میانافزار درونخطی بدون نوشتن کل کلاس میانافزار فراهم میکند:
use Closure;use Illuminate\Http\Request; /** * Get the middleware that should be assigned to the controller. */public static function middleware(): array{ return [ function (Request $request, Closure $next) { return $next($request); }, ];}
کنترل کننده های منابع
اگر هر مدل Eloquent را در برنامه خود به عنوان یک "منبع" در نظر می گیرید، معمول است که مجموعه اقدامات مشابهی را در برابر هر منبع در برنامه خود انجام دهید. به عنوان مثال، تصور کنید برنامه شما شامل یک
Photo
مدل و یک
Movie
مدل است. این احتمال وجود دارد که کاربران بتوانند این منابع را ایجاد، خواندن، به روز رسانی یا حذف کنند.
به دلیل این مورد رایج، مسیریابی منابع لاراول مسیرهای معمولی ایجاد، خواندن، به روز رسانی و حذف ("CRUD") را به یک کنترلر با یک خط کد اختصاص می دهد. برای شروع، میتوانیم از گزینه
make:controller
دستور Artisan
--resource
برای ایجاد سریع یک کنترلکننده برای مدیریت این اقدامات استفاده کنیم:
php artisan make:controller PhotoController --resource
این دستور یک کنترلر در
app/Http/Controllers/PhotoController.php
. کنترل کننده شامل یک روش برای هر یک از عملیات منابع موجود خواهد بود. در مرحله بعد، می توانید یک مسیر منبع را ثبت کنید که به کنترل کننده اشاره می کند:
use App\Http\Controllers\PhotoController; Route::resource('photos', PhotoController::class);
این اعلان مسیر واحد، مسیرهای متعددی را برای انجام انواع اقدامات روی منبع ایجاد می کند. کنترلکننده تولید شده قبلاً روشهایی را برای هر یک از این اقدامات درج شده است. به یاد داشته باشید که همیشه می توانید با اجرای دستور Artisan یک نمای کلی از مسیرهای برنامه خود داشته باشید
route:list
.
حتی ممکن است با ارسال یک آرایه به متد، بسیاری از کنترل کننده های منابع را به طور همزمان ثبت کنید
resources
:
Route::resources([ 'photos' => PhotoController::class, 'posts' => PostController::class,]);
اقدامات انجام شده توسط کنترل کننده های منابع
فعل | URI | عمل | نام مسیر |
---|---|---|---|
گرفتن | /photos |
فهرست مطالب | photos.index |
گرفتن | /photos/create |
ايجاد كردن | عکس. ایجاد |
پست | /photos |
فروشگاه | photos.store |
گرفتن | /photos/{photo} |
نشان می دهد | عکس.نمایش |
گرفتن | /photos/{photo}/edit |
ویرایش کنید | photos.edit |
PUT/PATCH | /photos/{photo} |
به روز رسانی | photos.update |
حذف | /photos/{photo} |
از بین رفتن | عکس. تخریب |
سفارشی کردن رفتار مدل گمشده
به طور معمول، اگر یک مدل منبع محدود به طور ضمنی یافت نشود، یک پاسخ HTTP 404 ایجاد می شود. با این حال، می توانید این رفتار را با فراخوانی
missing
روش هنگام تعریف مسیر منبع خود سفارشی کنید. این
missing
روش بسته شدنی را میپذیرد که اگر یک مدل به طور ضمنی برای هیچ یک از مسیرهای منبع پیدا نشود، فراخوانی میشود:
use App\Http\Controllers\PhotoController;use Illuminate\Http\Request;use Illuminate\Support\Facades\Redirect; Route::resource('photos', PhotoController::class) ->missing(function (Request $request) { return Redirect::route('photos.index'); });
مدل های نرم حذف شده
به طور معمول، اتصال مدل ضمنی مدلهایی را که بهصورت نرمافزاری حذف
شدهاند بازیابی نمیکند
و در عوض یک پاسخ HTTP 404 را برمیگرداند. با این حال، میتوانید به فریمورک دستور دهید تا مدلهای حذف شده نرم را با فراخوانی
withTrashed
روش در هنگام تعریف مسیر منبع خود مجاز کند:
use App\Http\Controllers\PhotoController; Route::resource('photos', PhotoController::class)->withTrashed();
فراخوانی
withTrashed
بدون آرگومان به مدل های نرم حذف شده برای
مسیرهای منبع
show
،
edit
و و .
update
شما می توانید زیر مجموعه ای از این مسیرها را با ارسال یک آرایه به
withTrashed
متد مشخص کنید:
Route::resource('photos', PhotoController::class)->withTrashed(['show']);
تعیین مدل منبع
اگر از اتصال مدل مسیر
استفاده میکنید
و میخواهید که روشهای کنترلکننده منبع، نمونهای از مدل را تایپ کنند، میتوانید
--model
هنگام تولید کنترلکننده از این گزینه استفاده کنید:
php artisan make:controller PhotoController --model=Photo --resource
ایجاد درخواست های فرم
میتوانید
--requests
هنگام تولید یک کنترلکننده منبع، این گزینه را ارائه دهید تا به Artisan دستور دهد
کلاسهای درخواست فرم
برای روشهای ذخیرهسازی و بهروزرسانی کنترلکننده را ایجاد کند:
php artisan make:controller PhotoController --model=Photo --resource --requests
مسیرهای منابع جزئی
هنگام اعلام مسیر منبع، میتوانید زیرمجموعهای از اقداماتی را که کنترلر باید انجام دهد، به جای مجموعه کامل اقدامات پیشفرض مشخص کنید:
use App\Http\Controllers\PhotoController; Route::resource('photos', PhotoController::class)->only([ 'index', 'show']); Route::resource('photos', PhotoController::class)->except([ 'create', 'store', 'update', 'destroy']);
مسیرهای منبع API
هنگام اعلام مسیرهای منبعی که توسط APIها مصرف می شوند، معمولاً می خواهید مسیرهایی را که الگوهای HTML را ارائه می دهند حذف
create
کنید
edit
. برای راحتی، می توانید از
apiResource
روشی برای حذف خودکار این دو مسیر استفاده کنید:
use App\Http\Controllers\PhotoController; Route::apiResource('photos', PhotoController::class);
شما می توانید با ارسال یک آرایه به متد، بسیاری از کنترل کننده های منبع API را به طور همزمان ثبت کنید
apiResources
:
use App\Http\Controllers\PhotoController;use App\Http\Controllers\PostController; Route::apiResources([ 'photos' => PhotoController::class, 'posts' => PostController::class,]);
create
برای تولید سریع یک کنترلکننده منبع API که شامل یا
edit
متدها
نمیشود ،
--api
هنگام اجرای
make:controller
دستور از سوئیچ استفاده کنید:
php artisan make:controller PhotoController --api
منابع تو در تو
گاهی اوقات ممکن است لازم باشد مسیرهایی را برای یک منبع تودرتو تعریف کنید. به عنوان مثال، یک منبع عکس ممکن است چندین نظر داشته باشد که ممکن است به عکس پیوست شود. برای قرار دادن کنترل کننده های منبع، می توانید از نماد "نقطه" در اعلان مسیر خود استفاده کنید:
use App\Http\Controllers\PhotoCommentController; Route::resource('photos.comments', PhotoCommentController::class);
این مسیر یک منبع تودرتو را ثبت می کند که ممکن است با URI هایی مانند زیر قابل دسترسی باشد:
/photos/{photo}/comments/{comment}
محدوده منابع تودرتو
ویژگی الزام آور مدل ضمنی
لاراول
می تواند به طور خودکار پیوندهای تودرتو را محدود کند به طوری که تأیید شود که مدل فرزند حل شده متعلق به مدل والد است. با استفاده از این
scoped
روش هنگام تعریف منبع تودرتو، می توانید محدوده خودکار را فعال کنید و همچنین به لاراول دستور دهید که منبع فرزند توسط کدام فیلد بازیابی شود. برای اطلاعات بیشتر در مورد نحوه انجام این کار، لطفاً به مستندات
مسیرهای منبع محدوده
مراجعه کنید .
لانه سازی کم عمق
اغلب، داشتن شناسه والد و فرزند در یک URI کاملاً ضروری نیست، زیرا شناسه فرزند در حال حاضر یک شناسه منحصر به فرد است. هنگام استفاده از شناسههای منحصربهفرد مانند کلیدهای اصلی افزایش خودکار برای شناسایی مدلهای خود در بخشهای URI، میتوانید از «تودرتوی سطحی» استفاده کنید:
use App\Http\Controllers\CommentController; Route::resource('photos.comments', CommentController::class)->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
آرایه با نام مسیرهای دلخواه خود لغو کنید:
use App\Http\Controllers\PhotoController; Route::resource('photos', PhotoController::class)->names([ 'create' => 'photos.build']);
نامگذاری پارامترهای مسیر منبع
به طور پیش فرض،
Route::resource
پارامترهای مسیر را برای مسیرهای منبع شما بر اساس نسخه "تکین" نام منبع ایجاد می کند. شما به راحتی می توانید این را بر اساس هر منبع با استفاده از
parameters
روش لغو کنید. آرایه ارسال شده به
parameters
متد باید یک آرایه انجمنی از نام منابع و نام پارامترها باشد:
use App\Http\Controllers\AdminUserController; Route::resource('users', AdminUserController::class)->parameters([ 'users' => 'admin_user']);
مثال بالا URI زیر را برای مسیر منبع تولید می کند
show
:
/users/{admin_user}
مسیرهای منابع محدوده
ویژگی اتصال مدل ضمنی محدودهای
لاراول
میتواند بهطور خودکار پیوندهای تودرتو را محدود کند، به طوری که تأیید شود که مدل فرزند حلشده متعلق به مدل والد است. با استفاده از این
scoped
روش هنگام تعریف منبع تودرتو، می توانید محدوده خودکار را فعال کنید و همچنین به لاراول دستور دهید که منبع فرزند با کدام فیلد باید بازیابی شود:
use App\Http\Controllers\PhotoCommentController; Route::resource('photos.comments', PhotoCommentController::class)->scoped([ 'comment' => 'slug',]);
این مسیر یک منبع تودرتو با محدوده را ثبت می کند که ممکن است با URI هایی مانند موارد زیر قابل دسترسی باشد:
/photos/{photo}/comments/{comment:slug}
هنگام استفاده از یک اتصال ضمنی با کلید سفارشی به عنوان پارامتر مسیر تودرتو، لاراول به طور خودکار محدوده پرس و جو را برای بازیابی مدل تودرتو توسط والد خود با استفاده از قراردادها برای حدس زدن نام رابطه روی والد، بررسی می کند. در این حالت، فرض می شود که
Photo
مدل دارای رابطه ای به نام
comments
(جمع نام پارامتر مسیر) است که می تواند برای بازیابی
Comment
مدل استفاده شود.
بومی سازی URI های منبع
به طور پیش فرض،
Route::resource
URI های منبع را با استفاده از افعال انگلیسی و قوانین جمع ایجاد می کند. اگر نیاز به بومی سازی افعال
create
و
edit
عمل دارید، می توانید از
Route::resourceVerbs
روش استفاده کنید. این ممکن است در ابتدای روش
boot
در برنامه شما انجام شود
App\Providers\AppServiceProvider
:
/** * Bootstrap any application services. */public function boot(): void{ Route::resourceVerbs([ 'create' => 'crear', 'edit' => 'editar', ]);}
پلورالیزر لاراول از
چندین زبان مختلف پشتیبانی می کند که می توانید بر اساس نیاز خود پیکربندی کنید
. هنگامی که افعال و زبان جمع سازی سفارشی شدند، یک ثبت مسیر منبع مانند
Route::resource('publicacion', PublicacionController::class)
URI های زیر را تولید می کند:
/publicacion/crear /publicacion/{publicaciones}/editar
تکمیل کنترل کننده های منابع
اگر نیاز به اضافه کردن مسیرهای اضافی به کنترلکننده منبع فراتر از مجموعه پیشفرض مسیرهای منبع دارید، باید آن مسیرها را قبل از فراخوانی متد تعریف کنید
Route::resource
. در غیر این صورت، مسیرهای تعریف شده توسط
resource
روش ممکن است ناخواسته بر مسیرهای تکمیلی شما اولویت داشته باشند:
use App\Http\Controller\PhotoController; Route::get('/photos/popular', [PhotoController::class, 'popular']);Route::resource('photos', PhotoController::class);
به یاد داشته باشید که کنترلرهای خود را متمرکز نگه دارید. اگر متوجه شدید که به طور معمول به روشهایی خارج از مجموعه اقدامات معمول منابع نیاز دارید، کنترل کننده خود را به دو کنترلر کوچکتر تقسیم کنید.
کنترل کننده های منابع Singleton
گاهی اوقات، برنامه شما منابعی دارد که ممکن است فقط یک نمونه داشته باشد. به عنوان مثال، "نمایه" یک کاربر را می توان ویرایش یا به روز کرد، اما یک کاربر ممکن است بیش از یک "نمایه" نداشته باشد. به همین ترتیب، یک تصویر ممکن است یک "تصویر کوچک" داشته باشد. این منابع "منابع تکی" نامیده می شوند، به این معنی که ممکن است یک و تنها یک نمونه از منبع وجود داشته باشد. در این سناریوها، می توانید یک کنترل کننده منبع "singleton" را ثبت کنید:
use App\Http\Controllers\ProfileController;use Illuminate\Support\Facades\Route; Route::singleton('profile', ProfileController::class);
تعریف منبع singleton در بالا مسیرهای زیر را ثبت می کند. همانطور که می بینید، مسیرهای "ایجاد" برای منابع تکی ثبت نمی شوند، و مسیرهای ثبت شده یک شناسه را نمی پذیرند زیرا ممکن است تنها یک نمونه از منبع وجود داشته باشد:
فعل | URI | عمل | نام مسیر |
---|---|---|---|
گرفتن | /profile |
نشان می دهد | نمایه.نمایش |
گرفتن | /profile/edit |
ویرایش کنید | پروفایل.ویرایش |
PUT/PATCH | /profile |
به روز رسانی | profile.update |
منابع Singleton همچنین ممکن است در یک منبع استاندارد تودرتو باشند:
Route::singleton('photos.thumbnail', ThumbnailController::class);
در این مثال،
photos
منبع تمام
مسیرهای منبع استاندارد را
دریافت می کند . با این حال،
thumbnail
منبع یک منبع تک تن با مسیرهای زیر خواهد بود:
فعل | URI | عمل | نام مسیر |
---|---|---|---|
گرفتن | /photos/{photo}/thumbnail |
نشان می دهد | عکسها.تصویر کوچک.نمایش |
گرفتن | /photos/{photo}/thumbnail/edit |
ویرایش کنید | photos.thumbnail.edit |
PUT/PATCH | /photos/{photo}/thumbnail |
به روز رسانی | photos.thumbnail.update |
منابع Singleton قابل ایجاد
گاهی اوقات، ممکن است بخواهید مسیرهای ایجاد و ذخیره سازی را برای یک منبع singleton تعریف کنید. برای انجام این کار، میتوانید
creatable
در هنگام ثبت مسیر منبع singleton از روش استفاده کنید:
Route::singleton('photos.thumbnail', ThumbnailController::class)->creatable();
در این مثال مسیرهای زیر ثبت خواهند شد. همانطور که می بینید، یک
DELETE
مسیر نیز برای منابع تکی قابل ایجاد ثبت می شود:
فعل | URI | عمل | نام مسیر |
---|---|---|---|
گرفتن | /photos/{photo}/thumbnail/create |
ايجاد كردن | photos.thumbnail.create |
پست | /photos/{photo}/thumbnail |
فروشگاه | photos.thumbnail.store |
گرفتن | /photos/{photo}/thumbnail |
نشان می دهد | عکسها.تصویر کوچک.نمایش |
گرفتن | /photos/{photo}/thumbnail/edit |
ویرایش کنید | photos.thumbnail.edit |
PUT/PATCH | /photos/{photo}/thumbnail |
به روز رسانی | photos.thumbnail.update |
حذف | /photos/{photo}/thumbnail |
از بین رفتن | عکسها.تصویر کوچک.از بین بردن |
اگر می خواهید لاراول
DELETE
مسیر را برای یک منبع singleton ثبت کند اما مسیرهای ایجاد یا ذخیره سازی را ثبت نکند، می توانید از
destroyable
روش زیر استفاده کنید:
Route::singleton(...)->destroyable();
API Singleton Resources
این
apiSingleton
روش ممکن است برای ثبت یک منبع تکی استفاده شود که از طریق یک API دستکاری می شود، بنابراین مسیرهای
create
و
edit
مسیرها غیرضروری می شوند:
Route::apiSingleton('profile', ProfileController::class);
البته، منابع API singleton نیز ممکن است باشد ، که
برای منبع
creatable
ثبت
store
و مسیر میکند:
destroy
Route::apiSingleton('photos.thumbnail', ProfileController::class)->creatable();
تزریق وابستگی و کنترلرها
تزریق سازنده
کانتینر سرویس لاراول برای حل همه کنترلرهای لاراول استفاده می شود. در نتیجه، میتوانید هر نوع وابستگی را که کنترلر شما ممکن است در سازنده خود به آن نیاز داشته باشد را تایپ کنید. وابستگی های اعلام شده به طور خودکار حل می شوند و به نمونه کنترلر تزریق می شوند:
<?php namespace App\Http\Controllers; use App\Repositories\UserRepository; class UserController extends Controller{ /** * Create a new controller instance. */ public function __construct( protected UserRepository $users, ) {}}
روش تزریق
علاوه بر تزریق سازنده، میتوانید وابستگیهای متدهای کنترلر خود را نیز تایپ کنید. یک مورد رایج برای تزریق روش، تزریق
Illuminate\Http\Request
نمونه به روشهای کنترلکننده است:
<?php namespace App\Http\Controllers; use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request; class UserController extends Controller{ /** * Store a new user. */ public function store(Request $request): RedirectResponse { $name = $request->name; // Store the user... return redirect('/users'); }}
اگر روش کنترلر شما نیز انتظار ورودی از پارامتر مسیر را دارد، آرگومان های مسیر خود را بعد از وابستگی های دیگر فهرست کنید. برای مثال، اگر مسیر شما به این صورت تعریف شده باشد:
use App\Http\Controllers\UserController; Route::put('/user/{id}', [UserController::class, 'update']);
همچنان می توانید با تعریف روش کنترلر خود به صورت زیر، پارامتر
را تایپ کنید
Illuminate\Http\Request
و به پارامتر خود دسترسی پیدا کنید :
id
<?php namespace App\Http\Controllers; use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request; class UserController extends Controller{ /** * Update the given user. */ public function update(Request $request, string $id): RedirectResponse { // Update the user... return redirect('/users'); }}