Middleware (میدل ویر) چیست؟
در لاراول middleware هایی علاوه بر تایید اعتبار می توان اضافه کرد یک middleware core (میدل ویر اصلی) ممکن است مسئول اضافه کردن انواع هدر های لازم در برنامه برای ترک یا افزوده شدن کاربر باشد همچنین یک middleware logging ممکن است درخواست هایی (request) در هنگام ورود کاربر به برنامه به هدر ها اضافه کند
فریم ورک لاراول دارای چند نوع مختلف middleware از جمله authentication و CSRF هستش همه این middleware ها در مسیر app/Http/Middleware ذخیره و در فایل kernel.php تعریف شده اند. درواقع میدل ویر ها یک واسط هستند که می توانند در بخش های مختلف برنامه برای اهداف مختلف مثل ثبت ویو محصولات، احراز هویت کاربران و ... مورد استفاده قرار گیرند یک مثال جالب مثل اجبار کاربر برای انجام یک کار مثل لاگین یا تکمیل اطلاعات پروفایل، که تا وقتی پروفایل خود را کامل نکرده باشد با استفاده از middleware تعریف شده ما، به صفحه مورد نظر برگشت داده شود.
تعريف middleware یا ساخت middleware در لاراول
تعریف middleware یا ساخت یک میدل ویر جدید با دستور make:middleware در Artisan command انجام می شود در مثال ذیل CheckAge نام میدل ویر تعریفی می باشد و بسته به کاربردش می تواند نام های متفاوتی داشته باشد.
php artisan make:middleware CheckAge
این دستور یک middleware با نام CheckAge در مسیر app/Http/Middleware ایجاد می کند و بنا به کد ذیل تا وقتی که سن ارسالی به برابر یا بزرگتر از عدد 200 نباشد شما به صفحه home برگشت داده می شوید. با درست بودن شرط نیز کاربر می تواند از این میان افزار عبور کند.
namespace App\Http\Middleware;
use Closure;
class CheckAge
{
public function handle($request, Closure $next)
{
if ($request->age <= 200) {
return redirect('home');
}
return $next($request);
}}
بعد از تعریف یک میدل ویر باید در فایل kernel.php در قسمت routeMiddleware نیز افزوده شود برای مثال CheckAge خواهیم داشت. عنوان age را می توان به مسیر مورد نظر اعمال کرد
protected $routeMiddleware = [
...
'age' => \App\Http\Middleware\CheckAge::class,
];
نحوه اعمال middleware به یک مسیر
Route::get('User','User\UserController@index')->middleware('age');
انواع مثال middleware
انواع مثال middleware بستگی به سبک شما در برنامه نویسی دارد چند مثال از کاربرد middleware را می توان به صورت ذیل عنوان کرد
- چک کردن یک مقدار (مثل سن کاربر)
- ثبت میزان بازدید در دیتابیس از آدرسی (url) که این میدل ویر را دارد
- چک کردن سطوح دسترسی
- چک کردن سطوح دسترسی برای پکیج های ACL مثل spatie یا zizaco
- ترکیب چند middleware با هم
- redirect کردن کاربر به صفحه مورد نظر
- کنترل میزان درخواست در یک مسیر یا تمام مسیرهای موجود (throttle)
- چک کردن توکن CRFS
- و ....
Before & After Middleware
شما می توانید middleware هایی تعریف کنید که قبل یا بعد از درخواست اجرا شود. Before & After Middleware نیز کاربردهای خود را دارد و نحوه استفاده بستگی به برنامه نویس دارد
BeforeMiddleware
php artisan make:middleware BeforeMiddleware
مثال از BeforeMiddleware
namespace App\Http\Middleware;
use Closure;
class BeforeMiddleware
{
public function handle($request, Closure $next)
{
// عملیات مورد نظرتان را بنویسید
return $next($request);
}
}
مثال از AfterMiddleware
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// بعد از درخواست مثلا یک رویداد ایجاد کنید
return $response;
}
}
ثبت middleware
Global Middleware ( میدل ویر عمومی )
Global Middleware در تمام درخواست های HTTP به برنامه شما اجرا خواهد شد اگر می خواهید یک Global Middleware تعریف کنید یعنی بدون اینکه بخواهید یک میدل ویر تعریف شده را در هر مسیر فراخوانی یا اعمال کنید در قسمت $middleware فایل kernel.php اضافه کنید تا در تمام درخواست های HTTP برنامه شما اجرا شود. نکته !!! به فکر این باشید که میدل ویر شما آیا نیازه در تمام درخواست ها اجرا بشه؟؟؟ اگه نه پس این بخش رو فراموش کنید. این بخش در فایل kernel.php به صورت ذیل تعریف شده است.
protected $middleware = [
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
];
اعمال middleware در Route
پس از معرفی یک middleware در فایل kernel.php باید آن را به مسیر مورد نظر خود اعمال کنید برای اعمال middleware در Route (مسیرهای خود در فایل های web.php یا api.php) به یکی را روش های ذیل اقدام کنید
اعمال فقط یک middleware
Route::get('admin/profile', function () {
// کدهای شما
})->middleware('auth'); // استفاده از میان افزار اعتبار سنجی لاگین کاربر
اعمال چندین middleware
Route::get('/', function () {
//
})->middleware('first', 'second'); استفاده از دو میدل ویر
روش دوم
Route::get('/', function () {
//
})->middleware(['first', 'second']); // معرفی به صورت آرایه ای و نسخه های قبلی لاراول
اعمال middleware با استفاده از نام کلاس
در این روش مستقیم از نام کلاس میدل ویر مورد نظر استفاده می شود و حتما باید کلاس مورد نظر در فایل web.php یا api.php قبل از اعمال use شود .
use App\Http\Middleware\CheckAge;
Route::get('admin/profile', function () {
//
})->middleware(CheckAge::class);
اعمال middleware در Controller
اعمال middleware در controller نیز مورد استفاده قرار می گیرد و بنا به شرایطی در پروژه ها ممکن است نیاز شما باشد به مثال ذیل توجه کنید
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'); // اعمال روی تمام متدها به جز متد مورد نظر
}
}
Middleware Groups
middleware groups به شما کمک می کند که به تعداد از middleware ها با اختصاص یک کلید دسترسی داشته باشید گروه بندی میدل ویر ها تا به راحتی بتوان در مسیر مورد نظر آنها را اعمال کرد. در فایل kernel.php بخش $middlewareGroups برای این کار تعبیه شده است.
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
], // کلید دسترسی وب با چندین میدل ویر
'api' => [
'throttle:60,1',
'auth:api',
],
];
مثال اعمال middlewareهای گروهی
Route::get('/', function () {
//
})->middleware('web');
Route::group(['middleware' => ['web']], function () {
});
نکته : میدل ویر web به صورت اتوماتیک از طریق فایل RouteServiceProvider به تمام مسیرهای فایل routes/web.php اعمال می شود.
Sorting Middleware
sorting middleware به اجرای ترتیب دار میدل ویرها می باشد هنگام اعمال به مسیرها به صورت چندتایی، اجرای middleware ها به ترتیب از اولین شروع و به آخرین ختم می شود اگر به هر عنوان شما این ترتیب را رعایت نکرده باشید می توانیددر فایل app/Http/Kernel.php بخش $middlewarePriority این ترتیب اجرا را مشخص کنید
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
Middleware Parameters
Middleware Parameters یا پارمترهای ورودی یک میدل ویر، شما با کمک این ویژگی در میدل ویرها می توانید پارامتر دیگری به میدل ویر خود پاس دهید به عنوان مثال ، اگر برنامه شما قبل از انجام یک عمل خاص باید تأیید کند که کاربر تأیید شده دارای "نقش" خاصی است ، می توانید یک میان افزار CheckRole ایجاد کنید که یک نقش را به عنوان یک آرگومان اضافی دریافت می کند. این پارامترهای اضافی باید بعد از پارامتر $next اعمال شوند.
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) {
// اگر کاربر دسترسی مورد نظر را نداشت این قسمت اجرا شود
}
return $next($request);
}
}
این پارامترهای اضافی middleware در لاراول در هنگام اعمال می تواند تعریف شود که بعد از اسم middleware تعریف شده در لاراول باید علامت : استفاده کرد و نام پارامتر خود را وارد کرد اگر چندین پارامتر قرار باشد اعمال شود از علامت کاما استفاده کنید.
Route::put('post/{id}', function ($id) {
//
})->middleware('role:editor');
مثال چندین Middleware Parameters
Route::put('post/{id}', function ($id) {
//
})->middleware('role:editor,manager');
Terminable Middleware
terminable middleware به معنای خاتمه دادن و در لاراول به معنای انجام یکسری دستورات پس از پاسخ به مرورگر می باشد. گاهی اوقات نیاز می باشد که پس از ارسال پاسخ HTTP به مرورگر، دستوراتی اجرا کنیم برای مثال میدل ویر session داده های session ها را پس از پاسخ به مرورگر برای ذخیره سازی در فایل های موقت، می نویسد. برای استفاده از متد terminate باید FastCGI در سرور شما نصب باشد.
namespace Illuminate\Session\Middleware;
use Closure;
class StartSession {
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
// اجرای دستوراتی مثل ذخیره جلسات و ...
}
}
متد terminate هر دونوع درخواست (request) و پاسخ (response) را باید دریافت کند. پس از تعریف یک middleware شامل متد teminate باید این میدل ویر را در فایل kernel.php نیز معرفی کنید یک مثال از نحوه استفاده از terminate middleware در لاراول را در ذیل مشاهده می کنید.
اجرای دستور برای اجرای ساخت یک میدل ویر با نام TerminateMiddleware
php artisan make:middleware TerminateMiddleware
یک فایل در پوشه میدل ویرها app/Http/Middleware/TerminateMiddleware.php با نام TerminateMiddleware ایجاد می شود که در بدنه آن برای تست کدهای ذیل را اعمال می کنیم
namespace App\Http\Middleware;
use Closure;
class TerminateMiddleware {
public function handle($request, Closure $next) {
echo "Executing statements of handle method of TerminateMiddleware.";
return $next($request);
}
public function terminate($request, $response) {
echo "Executing statements of terminate method of TerminateMiddleware.";
}
}
میدل ویر TerminateMiddleware را در فایل app\Http\Kernel.php معرفی می کنیم به صورت ذیل
protected $routeMiddleware = [
...
'terminate' => \App\Http\Middleware\TerminateMiddleware ::class
];
سپس یک کنترلر با نام ABCController ایجاد می کنیم
php artisan make:controller ABCController
یک متد با نام index داخل بدنه این کنترلر تعریف می کنیم
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class ABCController extends Controller {
public function index() {
echo "ABC Controller.";
}
}
و در آخر مسیر دسترسی به آن را تعریف می کنیم که میدل ویر مورد نظر ما بر روی این مسیر اعمال شده است.
Route::get('terminate','ABCController@index')->middleware('terminate');
دستور php artisan serve را اجرا کنید سپس این مسیر را در مرورگر خود باز کنید
http://localhost:8000/terminate
شما این پیغام را در خروجی مشاهده خواهید کرد
Executing statements of terminate method of TerminateMiddleware.
ABC Controller.
Executing statements of terminate method of TerminateMiddleware.
یادگیری عملی لاراول: آموزش لاراول
خیلی عالی و پر ملات
خوشحالیم که یک آموزش خوبی برای شما بود