نسخه:

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

معرفی

به جای اینکه تمام منطق رسیدگی به درخواست خود را به عنوان بسته در فایل های مسیر خود تعریف کنید، ممکن است بخواهید این رفتار را با استفاده از کلاس های "کنترل کننده" سازماندهی کنید. کنترلرها می توانند منطق رسیدگی به درخواست مرتبط را در یک کلاس واحد گروه بندی کنند. به عنوان مثال، یک UserController کلاس ممکن است تمام درخواست‌های دریافتی مربوط به کاربران، از جمله نمایش، ایجاد، به‌روزرسانی و حذف کاربران را مدیریت کند. به طور پیش فرض، کنترلرها در app/Http/Controllers دایرکتوری ذخیره می شوند.

کنترل کننده های نوشتن

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

بیایید نگاهی به نمونه ای از یک کنترل کننده اولیه بیندازیم. توجه داشته باشید که کنترل کننده کلاس کنترل کننده پایه شامل لاراول را گسترش می دهد App\Http\Controllers\Controller :

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Models\User;
 
class UserController extends Controller
{
/**
* Show the profile for a given user.
*
* @param int $id
* @return \Illuminate\View\View
*/
public function show($id)
{
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 کلاس فراخوانی می شود و پارامترهای مسیر به متد ارسال می شود.

کنترلرها نیازی به گسترش کلاس پایه ندارند . با این حال، شما به ویژگی های مناسبی مانند middleware و authorize روش ها دسترسی نخواهید داشت.

کنترلرهای تک اقدام

اگر یک اکشن کنترلر بسیار پیچیده باشد، ممکن است برای شما راحت باشد که یک کلاس کنترلر را به آن عمل اختصاص دهید. برای انجام این کار، می توانید یک __invoke روش واحد را در کنترلر تعریف کنید:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Models\User;
 
class ProvisionServer extends Controller
{
/**
* Provision a new web server.
*
* @return \Illuminate\Http\Response
*/
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');

یا، ممکن است برای شما راحت باشد که میان افزار را در سازنده کنترلر خود مشخص کنید. با استفاده از 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');
}
}

کنترلرها همچنین به شما این امکان را می دهند که با استفاده از یک بسته، میان افزار را ثبت کنید. این یک راه راحت برای تعریف یک میان افزار درون خطی برای یک کنترل کننده بدون تعریف کل کلاس میان افزار فراهم می کند:

$this->middleware(function ($request, $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');
});

مشخص کردن مدل منبع

اگر از اتصال مدل مسیر استفاده می‌کنید و می‌خواهید که روش‌های کنترل‌کننده منبع، نمونه‌ای از مدل را تایپ کنند، می‌توانید --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\RouteServiceProvider :

/**
* Define your route model bindings, pattern filters, etc.
*
* @return void
*/
public function boot()
{
Route::resourceVerbs([
'create' => 'crear',
'edit' => 'editar',
]);
 
// ...
}

هنگامی که افعال سفارشی شدند، یک ثبت مسیر منبع مانند Route::resource('fotos', PhotoController::class) URI های زیر را تولید می کند:

/fotos/crear
 
/fotos/{foto}/editar

تکمیل کنترل کننده های منابع

اگر نیاز به اضافه کردن مسیرهای اضافی به کنترل‌کننده منبع فراتر از مجموعه پیش‌فرض مسیرهای منبع دارید، باید آن مسیرها را قبل از فراخوانی متد تعریف کنید Route::resource . در غیر این صورت، مسیرهای تعریف شده توسط resource روش ممکن است ناخواسته بر مسیرهای تکمیلی شما اولویت داشته باشند:

use App\Http\Controller\PhotoController;
 
Route::get('/photos/popular', [PhotoController::class, 'popular']);
Route::resource('photos', PhotoController::class);

به یاد داشته باشید که کنترلرهای خود را متمرکز نگه دارید. اگر متوجه شدید که به طور معمول به روش‌هایی خارج از مجموعه اقدامات معمول منابع نیاز دارید، کنترل کننده خود را به دو کنترلر کوچکتر تقسیم کنید.

تزریق وابستگی و کنترلرها

تزریق سازنده

کانتینر سرویس لاراول برای حل همه کنترلرهای لاراول استفاده می شود. در نتیجه، می‌توانید هر نوع وابستگی را که کنترلر شما ممکن است در سازنده خود به آن نیاز داشته باشد را تایپ کنید. وابستگی های اعلام شده به طور خودکار حل می شوند و به نمونه کنترلر تزریق می شوند:

<?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 \App\Repositories\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 \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$name = $request->name;
 
//
}
}

اگر روش کنترلر شما نیز انتظار ورودی از پارامتر مسیر را دارد، آرگومان های مسیر خود را بعد از وابستگی های دیگر فهرست کنید. برای مثال، اگر مسیر شما به این صورت تعریف شده باشد:

use App\Http\Controllers\UserController;
 
Route::put('/user/{id}', [UserController::class, 'update']);

همچنان می توانید با تعریف روش کنترلر خود به صورت زیر، پارامتر را تایپ کنید Illuminate\Http\Request و به پارامتر خود دسترسی پیدا کنید : id

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
 
class UserController extends Controller
{
/**
* Update the given user.
*
* @param \Illuminate\Http\Request $request
* @param string $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
}