- پنجشنبه 20 دی 1397 ساعت 16:18
- 5.6.29
- در حال تکمیل
- منقضی شده
مقدمه
شاید بخواهید تا به جای تعریف کلوژر در فایلهای روت به عنوان لاجیک هندل کنندهی ریکوئستها، این رفتار را با استفاده از کلاسهای کنترلر سازماندهی کنید. کنترلرها میتوانند لاجیک هندل کردن ریکوئستهای مرتبط، را در قالب یک کلاس گروهبندی کنند. کنترلرها در دایرکتوری app/Http/Controllers
قرار میگیرند.
کنترلرهای پایه
تعریف کردن کنترلرها
مثال زیر یک کلاس پایه برای یک کنترلر است. توجه داشته باشید که این کنترلر از کلاس کنترلر پایهی لاراول مشتق شده است. کلاس پایه متدهای مناسبی مانند متد middleware
را که میتواند برای اَتَچ کردن میدلور به اکشنهای کنترلر استفاده شود، را ارائه میدهد.
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*
* @param int $id
* @return Response
*/
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\User;
use App\Http\Controllers\Controller;
class ShowProfile extends Controller
{
/**
* Show the profile for the given user.
*
* @param int $id
* @return Response
*/
public function __invoke($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
هنگامی که روتهایی برای کنترلرهای تک اکشنه رجیستر میکنید، نیازی به مشخص کردن متد برای آنها ندارید:
Route::get('user/{id}', 'ShowProfile');
با استفاده از آپشن --invokable
کامند آتیزان make:controller
میتوانید یک کنترلر تک اکشنه تولید کنید که در هنگام تولید این کنترلر، متد __invoke
در آن تعریف شده است:
php artisan make:controller ShowProfile --invokable
میدلورِ کنترلر
میدلورها میتوانند در فایلهای روت برای روتهای کنترها تعیین شوند:
Route::get('profile', 'UserController@show')->middleware('auth');
گرچه، روش مناسبتر، مشخص کردن میدلور در متد constructor کنترلر است. با استفاده از متد middleware
در constructor کنترلرتان، به راحتی میتوانید برای اکشن کنترلر، میدلور مشخص کنید. حتی میتوانید میدلوری را تنها به متدهای مشخصی از کلاس کنترلر محدود کنید:
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);
});
با اینکه میتوانید میدلوری را به مجموعهای از اکشنهای کنترلر تخصیص دهید؛ اما، این کار میتواند نشاندهنده این باشد که کنترلرتان خیلی در حال بزرگ شدن است. به جای این کار، کنترلرتان را به چندین کنترلر کوچکتر بشکنید.
ریسورس کنترلرها
مسیریابی ریسورسها در لاراول، روتهای CRUD معمول را تنها با یک خط کد، برای یک کنترلر تعیین میکند. برای مثال، ممکن است بخواهید کنترلری ایجاد کنید که تمام ریکوئستهای HTTP برای تصاویر ذخیره شده توسطط اپلیکیشنتان را هندل کند. با استفاده از کامند آرتیزان make:controller
، به سرعت میتوانید چنین کنترلری ایجاد کنید:
php artisan make:controller PhotoController --resource
این کامند یک کنترلر در app/Http/Controllers/PhotoController.php
تولید خواهد کرد. کنترلر تولید شده، حاوی یک متد برای هر عملیات ریسورسِ در دسترسی خواهد بود.
سپس، میتوانید یک روت ریسورسفول برای این کنترلر رجیستر کنید:
Route::resource('photos', 'PhotoController');
این روت به تنهایی چندین روت برای هندل کردن اکشنهای مختلف ریسورس را ایجاد میکند. کنترلر تولید شده، دارای متدهایی برای هر کدام از این اکشنها است که HTTP Verbها و URIهایی که توسط این اکشنها هندل میشوند از قبل برای آنها مشخص شده است.
با ارسال یک آرایه حاوی مسیر و کنترلر به متد resources
، میتوانید چندین ریسورس کنترلر را به یکباره رجیستر کنید:
Route::resources([
'photos' => 'PhotoController',
'posts' => 'PostController'
]);
اکشنهایی که توسط ریسورس کنترلر هندل میشوند
Verb | URI | Action | Route Name |
---|---|---|---|
GET | /photos |
index | photos.index |
GET | /photos/create |
create | photos.create |
POST | /photos |
store | photos.store |
GET | /photos/{photo} |
show | photos.show |
GET | /photos/{photo}/edit |
edit | photos.edit |
PUT/PATCH | /photos/{photo} |
update | photos.update |
DELETE | /photos/{photo} |
destroy | photos.destroy |
مشخص کردن مدلِ ریسورس
اگر از روت مدل بایندینگ (تزریق مدل به واسطه روت) استفاده میکنید و میخواهید که یک instance از مدل را به متدهای ریسورس کنترلر type-hint کنید، میتوانید هنگام تولید کنترلر، از آپشن --model
استفاده کنید:
php artisan make:controller PhotoController --resource --model=Photo
جعل متدهای فرم (Spoofing Form Methods)
از آنجایی که فرمهای HTML نمیتوانند ریکوئستهای PUT
و PATCH
و DELETE
را بسازند، برای جعل (تغییر) این HTTP verbها نیاز خواهید داشت تا یک فیلد هیدن با نیم _method
به فرم خود اضافه کنید. دایرکتیو @method
در بلید میتواند این فیلد را برایتان ایجاد کند:
<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 Resource)
هنگامی که ریسورس روتهایی تعریف میکنید که مختص APIها هستند؛ معمولا میخواهید روتهایی مانند create
و edit
را که تمپلت HTML نمایش میدهند را از ریسورس خارج کنید. با استفاده از متد apiResource
، میتوانید به صورت خودکار این دو روت را حذف کنید:
Route::apiResource('photos', 'PhotoController');
با ارسال یک آرایه به متد apiResources
، میتوانید چندین اِیپیآی ریسورس کنترلر را به صورت یکباره رجیستر کنید:
Route::apiResources([
'photos' => 'PhotoController',
'posts' => 'PostController'
]);
برای تولید سریع یک اِیپیآی ریسورس کنترلر که متدهای create
و edit
را اینکلود نمیکند، در هنگام اجرای کامند آرتیزان make:controller
، از سوئیچ --api
استفاده کنید:
php artisan make:controller API/PhotoController --api
نامگذاری ریسورس روتها
به صورت پیشفرض، تمامی اکشنهای ریسورس کنترلرها دارای یک نام مسیر هستند؛ با این وجود؛ با ارسال یک آرایه 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}
محلیسازی URIهای تولیدی ریسورسها
Route::resource
به صورت پیشفرض، URIهایی با verbهای انگلیسی برای ریسورسها تولید میکند. اگر میخواهید verbهای اکشنهای 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',
]);
}
هنگامی که verbها کاستومایز شدند، رجیستر کردن یک ریسورس روت مانند Route::resource('fotos', 'PhotoController')
منجر به تولید URIهای زیر خواهد شد:
/fotos/crear
/fotos/{foto}/editar
کامل کردن ریسورس کنترلرها
اگر میخواهید علاوه بر مجموعه ریسورس روتهای پیشفرض، روتهای بیشتری به یک ریسورس کنترلر اضافه کنید، باید روتهای مورد نظر خود را قبل از فراخوانی Route::resource
تعریف کنید؛ در غیر اینصورت، روتهایی که توسط متد resource
تعریف میشوند، ممکن است به صورت ناخواسته بر روتهای مکمل شما ارجحیت بیشتری داشته باشند.
Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');
به خاطر داشته باشید که کنترهایتان را متمرکز نگه دارید. اگر معمولا به متدهایی غیر از مجموعه اکشنهای ریسورسی معمول نیاز دارید، شکستن کنترلر به چندین کنترلر کوچکتر روش بهتری است.
تزریق وابستگی (Dependency Injection) و کنترلرها
تزریق سازنده (Constructor Injection)
در لاراول سرویس کانتینر برای ریزالو کردن تمامی کنترلرهای لاراول استفاده میشود. در نتیجه، قادر خواهید بود تا هر وابستگی را که کنترلرتان به آن نیاز دارد در constructor کنترلر type-hint کنید. دیپندنسیهای تعریف شده، به صورت خودکار ریزالو شده و به instance کنترلر اینجکت خواهند شد:
<?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;
}
}
طبیعتا، میتوانید هر کنترکتی از لاراول را type-hint کنید. اگر کانتینر بتواند آن کانترکت را ریزالو کند، میتوانید آن را type-hint کنید. بسته به اپلیکیشنتان، اینجکت کردن دیپندنسیها به کنترلرتان میتواند تستپذیری بهتری فراهم کند.
تزریق متد (Method Injection)
همچنین علاوه بر تزریق سازنده، میتوانید دیپندنسیها را به متدهای کنترلرتان type-hint کنید. یک موردِ استفاده معمول برای متد اینجکشن، اینجکت کردن instance (نمونه) 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
را type-hint کرده و با تعریف متد کنترلر خود به شکل زیر به پارامتر 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)
{
//
}
}
کش کردن روتها
روتهایی که بر پایه کلوژرها رجیستر میشوند، قابلیت کش شدن ندارند. برای استفاده از قابلیت کش کردن روتها، باید تمامی روتهایی که به شکل کلوژر رجیستر شدهاند را به کلاسهای کنترلر تبدیل کنید.
اگر اپلیکیشنتان تنها از روتهای بر پایه کنترلر استفاده میکند، باید از مزایای کش کردن روت ارائه شده توسط لاراول بهرهمند شوید. با کش کردن روتها، به میزان قابل توجهی زمانی که طول میکشد تا تمامی روتهای اپلیکیشنتان رجیستر شوند را کاهش میدهید. در برخی موارد، رجیستر کردن روتهایتان میتواند حتی تا 100 برابر سریعتر انجام شود. برای کش کردن روتها، تنها کافیست کامند آرتیزان route:cache
را اجرا کنید:
php artisan route:cache
پس از اجرای این کامند، فایل مربوط به روتهای کش شده در تمامی ریکوئستها لود خواهد شد. به خاطر داشته باشید، اگر نیاز به افزودن روت جدیدی دارید، باید مجددا روتها را کش کنید. به همین دلیل، کامند route:cache
را تنها باید در حین دپلوی کردن پروژهتان اجرا کنید.
برای پاک کردن فایل مربوط به روتهای کش شده، میتوانید از کامند route:clear
استفاده کنید:
php artisan route:clear
سایر پستهای داکیومنت
- پیشگفتار
- Release Notes ترجمه در ورژنهای بعدی
- راهنمای آپگرید ترجمه در ورژنهای بعدی
- Contribution Guide ترجمه در ورژنهای بعدی
- شروع
- نصب
- پیکربندی
- ساختار دایرکتوری ترجمه در ورژنهای بعدی
- Laravel Homestead ترجمه در ورژنهای بعدی
- Laravel Valet ترجمه در ورژنهای بعدی
- دپلویمنت ترجمه در ورژنهای بعدی
- مفاهیم معماری
- چرخه کار ریکوئستها
- Service Container ترجمه در ورژنهای بعدی
- سرویس پرووایدرها
- فسادها ترجمه در ورژنهای بعدی
- Contracts ترجمه در ورژنهای بعدی
- اصول اولیه
- مسیریابی
- میدلور
- حفاظت در مقابل حملات CSRF
- کنترلرها
- HTTP Requests ترجمه در ورژنهای بعدی
- HTTP Responses ترجمه در ورژنهای بعدی
- ویوها
- تولید URL
- HTTP Session ترجمه در ورژنهای بعدی
- Validation ترجمه در ورژنهای بعدی
- Error Handling ترجمه در ورژنهای بعدی
- Logging ترجمه در ورژنهای بعدی
- فرانتاند
- تمپلتهای Blade
- محلیسازی
- JavaScript & CSS Scaffolding ترجمه در ورژنهای بعدی
- Compiling Assets (Laravel Mix) ترجمه در ورژنهای بعدی
- امنیت
- Authentication ترجمه در ورژنهای بعدی
- API Authentication (Passport) ترجمه در ورژنهای بعدی
- Authorization ترجمه در ورژنهای بعدی
- Encryption ترجمه در ورژنهای بعدی
- Hashing ترجمه در ورژنهای بعدی
- Resetting Passwords ترجمه در ورژنهای بعدی
- مباحث عمیقتر
- Artisan Console ترجمه در ورژنهای بعدی
- Broadcasting ترجمه در ورژنهای بعدی
- Cache ترجمه در ورژنهای بعدی
- Collections ترجمه در ورژنهای بعدی
- Events ترجمه در ورژنهای بعدی
- File Storage ترجمه در ورژنهای بعدی
- Helpers ترجمه در ورژنهای بعدی
- Mail ترجمه در ورژنهای بعدی
- Notifications ترجمه در ورژنهای بعدی
- Package Development ترجمه در ورژنهای بعدی
- Queues ترجمه در ورژنهای بعدی
- Task Scheduling ترجمه در ورژنهای بعدی
- دیتابیس
- دیتابیس: شروع ترجمه در ورژنهای بعدی
- Database: Query Builder ترجمه در ورژنهای بعدی
- دیتابیس: صفحهبندی
- دیتابیس: مایگریشن
- دیتابیس: سیدینگ
- Redis ترجمه در ورژنهای بعدی
- Eloquent ORM
- Eloquent: Getting Started ترجمه در ورژنهای بعدی
- Eloquent: Relationships ترجمه در ورژنهای بعدی
- Eloquent: Collections ترجمه در ورژنهای بعدی
- Eloquent: Mutators ترجمه در ورژنهای بعدی
- Eloquent: API Resources ترجمه در ورژنهای بعدی
- Eloquent: Serialization ترجمه در ورژنهای بعدی
- Testing
- Testing: Getting Started ترجمه در ورژنهای بعدی
- HTTP Tests ترجمه در ورژنهای بعدی
- Browser Tests (Laravel Dusk) ترجمه در ورژنهای بعدی
- Database Testing ترجمه در ورژنهای بعدی
- Mocking ترجمه در ورژنهای بعدی
- Official Packages
- Laravel Cashier ترجمه در ورژنهای بعدی
- Envoy Task Runner ترجمه در ورژنهای بعدی
- Laravel Horizon ترجمه در ورژنهای بعدی
- API Authentication (Passport) ترجمه در ورژنهای بعدی
- Laravel Scout ترجمه در ورژنهای بعدی
- Laravel Socialite ترجمه در ورژنهای بعدی