middleware در لاراول (میدل ویر)

middleware در لاراول (میدل ویر)

middleware (میدل ویر) یک مکانیزم مناسب برای فیلتر کردن درخواست های HTTP که وارد برنامه شما می شوند فراهم می کند این همان تعریف معنی middleware می باشد برای مثال لاراول دارای یک middleware با عنوان verifies دارد که اعتبار کاربر برنامه شما تایید می کند و در صورت عدم احراز هویت، کاربر توسط این middleware به صفحه ورود (login) هدایت می شود و در صورت تایید نیز به شما اجازه ادامه کار در محیط برنامه داده می شود.

زمان مطالعه: 3 دقیقه
بازدید: 2528
پرسش و پاسخ: 2

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.

یادگیری عملی لاراول: آموزش لاراول 

بهزاد میرزازاده
مسیر درست با پرسش های درست ساخته می شود

مشاهده تمام مطالب نویسنده