نسخه:

کنترل کننده ها

معرفی

به جای اینکه تمام منطق رسیدگی به درخواست خود را به عنوان بسته در فایل های مسیر خود تعریف کنید، ممکن است بخواهید این رفتار را با استفاده از کلاس های "کنترل کننده" سازماندهی کنید. کنترلرها می توانند منطق رسیدگی به درخواست مرتبط را در یک کلاس واحد گروه بندی کنند. به عنوان مثال، یک 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');
}
}