میان افزارها (Middleware) در برنامه های نوشته شده توسط فریم ورک لاراول و صد البته در دیگر فریم ورک ها مانند ASP.NET به عنوان پلی هستند میان درخواست (Requset) ورودی و پاسخ (Response) که باید به کاربر نشان داده شود. در واقع میان افزارها به عنوان فیلترهایی بر روی درخواست های ورودی هستند که به کلیه درخواست ها گوش می دهند و در صورت ورود یک درخواست ویژه، واکنش (پاسخ) مناسب را می دهند.

به طور مثال می تواند میان افزاری وجود داشته باشد که بررسی می کند که آیا کاربر احراز هویت (Atuthenticated) شده است یا نه. اگر کاربر احراز هویت شده باشد، پس کاربر به صفحه خانگی (Home Page) هدایت (Redirect) می شود در غیر این صورت به صفحه ورود کاربران (Login Page) هدایت خواهد شد. در مطلب های بعدی دو مثال از کاربرد میان افزارها گفته ایم که از آنها به منظور ایجاد یک احراز هویت پایه (Basic Authentication) و ایجاد منوها (Menu) استفاده می شود.

ایجاد میان افزار در لاراول

برای ایجاد میان افزار باید از دستور php artisan make:middleware استفاده کنیم. تمامی میان افزارها درون مسیر app/Http/Middleware قرار دارند. در مثال زیر یک میان افزار به نام CheckAge ایجاد کرده ایم. هدف از آن تنها و تنها معرفی ساختار و بدنه میان افزارها است.

در شکل بالا دستوری که برای ایجاد میان افزاری به نام CheckAge استفاده شده، مشخص شده است. همچنین محل ذخیره سازی فایل CheckAge.php نیز نشان داده شده است. در ادامه مطلب در مورد این فایل صحبت می کنیم. فایل دیگری که نشانه گذاری شده، فایل Kernel.php است، در ادامه نیز در مورد این فایل صحبت شده است اما توجه کنید که این فایل در مسیر app/Http قرار دارد.

محتوای فایل میان افزار

پس از اجرای دستور php artisan make:middleware که همراه آن نام میان افزار نیز می آید، یک فایل همنام با پسوند php در مسیر app/Http/Middleware ایحاد می شود که حاوی یک کلاس همنام با میان افزار ایجاد شده است. قطعه کد و شکل زیر به طور مثال محتوای فایل CheckAge.php را نشان می دهند. همانطور که در خط سوم کد زیر می بینید، کلاس CheckAge در فضای نام App/Http/Middleware قرار دارد. همچنین کلاس Closure نیز در خط خط ۵ و توسط دستور use Closure به فایل ضمیمه شده است.

در قطعه کد زیر و درون بدنه متد ()handle میان افزاری را تعریف کردهیم که اگر در درخواست ارسال شده سن بیشتر از ۲۰۰ سال باشد، کاربر اجازه ادامه کار بر روی سایت را دارد. توجه کنید این تنها یک مثال از ساختار و بدنه کلاس های میان افزارها است.

وظیفه متد ()handle همانطور که از نامش مشخص است، اداره کردن (Handle) درخواست های ورودی است. اما این درخواست ها چگونه درون لاراول شناخته می شوند؟ همانطور که پیش از این نیز توضیح داده بودیم، در لاراول، یک درخواست از طریق نوشتن یک مسیر (Route) و معمولا درون فایل web.php شناخته و تعریف می شود.در واقع اگر عدد متغیر age$ کمتر یا مساوی ۲۰۰ باشد، پس کاربر مجدد و همواره به صفحه خانگی هدایت می شود. در لاراول هدایت کردن (Redirect) یک درخواست به صفحه دیگر، توسط تابع ()redirect انجام می شود.

در غیر این صورت اگر مقدار متغیر age$ بیشتر از ۲۰۰ باشد، پس لاراول به کاربر اجازه ادامه کار بر روی سایت را می دهد. در واقع در خط ۲۲ و توسط عبارت زیر درخواست کاربر به لاراول فرستاده می شود. بنابراین متوجه می شویم که میان افزار مطابق نام آن، پلی میان درخواست ورودی و پاسخ خروجی است به طوری که بر روی همه یا چند و یا تنها یکی از درخواست های کاربر گوش می دهد و بر روی درخواست ها کنترل و نظارت دارد.

همانطور که دیدید پاسخ می تواند یک هدایت به صفحه دیگری باشد. در مطب های بعدی خواهیم دید که می توانیم از بسته های نوشته شده در لاراول برای ایجاد منو و نوار ناوبری (Navigation Bar) سایت استفاده کنیم. در این مورد از میان افزارها استفاده می کنیم تا طبق درخواست ورودی، یک نوار ناوبری را نشان دهیم.

پیش و پس از میان افزار

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

شکل زیر ساختار و عملکرد کلی میان افزارها را نشان می دهد. به طور نمونه مطابق شکل زیر یک درخواست ورودی از طریق مسیر users/ که مثلا معادل آدرس http://api.my-domain.ir/users است به لاراول ارسال شده است. در صفحه users فهرست تمامی کاربران از پایگاه داده واکشی (Retrive) می شوند و سپس درون صفحه نشان داده می شوند. اما پیش از (Before) اجازه داده به درخواست، باید توسط یک میان افزار یک سری از بررسی ها مانند اینکه آیا کاربر احراز هویت شده (Authenticated) شده است؟ آیا یک CSRF Token معتبر وجود دارد؟

پس از تایید نیازمندهای تعیین شده درون میان افزار، پاسخ باید آماده شود. به طور مثال باید کوکی ها (Coockie) به پاسخ افزوده شوند. همچنین می توانید پس از میان افزار رکوردهای بدست آمده از پایگاه داده را کَش (Cache) کنید تا در زمان درخواست بعدی و پیش از میان افزار ابتدا فضای کَش برای بدست اوردن نتیجه مورد جستجو قرار گیرد و در صورت نبود پاسخ، به سراغ پایگاه داده برود.

پس از تایید نیازمندهای تعیین شده درون میان افزار، پاسخ باید آماده شود. به طور مثال باید کوکی ها (Coockie) به پاسخ افزوده شوند. همچنین می توانید پس از میان افزار رکوردهای بدست آمده از پایگاه داده را کَش (Cache) کنید تا در زمان درخواست بعدی و پیش از میان افزار ابتدا فضای کَش برای بدست اوردن نتیجه مورد جستجو قرار گیرد و در صورت نبود پاسخ، به سراغ پایگاه داده برود.

قطعه کد زیر حالت کلی یک کلاس میان افزار را نشان می دهد که پیش از درخواست انجام می شود. همانطور که می بینید قطعه کدها باید پیش از دستور ;(return $next($request نوشته شوند.

قطعه کد زیر حالت کلی یک کلاس میان افزار را نشان می دهد که پیش از درخواست انجام می شود. همانطور که می بینید قطعه کدها باید پس از دستور ;(response = $next($request$ و پیش از دستور ;return $response نوشته شوند.

ثبت میان افزار در لاراول

برای اینکه میان افزارها بتوانند بر روی درخواست های HTTP اجرا شود، باید آنها را درون فایل app/Http/Kernel.php و به در آرایه ای به نام middleware$ درج کنیم. کد زیر مقادیر (مسیرهای) پیش فرض مربوط به میان افزارهای پیش فرضی را نشان می دهد که همراه با ایجاد پروژه لاراول به صورت خودکار ایجاد شده و به درون آرایه middleware$ افزوده شده اند.

شکل زیر نشان می دهد که میان افزار CheckAge را به انتهای فهرست (آرایه – لیست) middleware$ اضافه کرده ایم.

انتساب میان افزار به مسیرها

کار دیگری که باید پس از ثبت میان افزار انجام دهیم، معرفی یا انتساب میان افزار به مسیرهای تعریف شده درون لاراول است. برای این کار باید از آرایه انجمنی به نام routeMiddleware$ در همان فایل Kernel.php در مسیر app/Http استفاده کنیم. قطعه کد زیر مقادیر پیش فرض آرایه routeMiddleware$ را نشان می دهد. هر خط از آرایه زیر یک نام به هر یک از میان افزارها انتساب داده شده است که پس از این باید از این نام را به مسیر انتساب می دهیم.

پس از اینکه میان افزار را در فایل Kernel.php مشخص کردیم نوبت به این می رسد که توسط متدی به نام ()middleware یک میان افزار را به یک مسیر (Route) اضافه کنیم. این متد نام یکی از میان افزارهای تعریف شده درون آرایه routeMiddleware$ را دریافت می کند. کد زیر نمونه ای از چگونگی انتساب میان افزار به یک مسیر را نشان می دهد که از تابع بی نام استفاده کرده است. همچنین اگر از نام کنترل گر نیز در مسیر استفاده کرده اید، بازهم شیوه کلی استفاده از متد ()middleware به همین صورت است.

همچنین مطابق کد زیر می توانیم بیش از یک میان افزار را به مسیر انتساب دهیم. قاعدتا ترتیب اجرا و اعمال میان افزار از سمت چپ ترین تا سمت راست ترین نامی است که در متد ()middleware تعیین کرده ایم.

گروهی از میان افزارها

اگر نیاز دارید تا چندین میان افزار را در غالب یک نام گروهی بندی کنید و سپس از این نام برای انتساب گروه میان افزارها به مسیرها استفاده کنید، باید از درون فایل Kernel.php از آرایه middlewareGroups$ استفاده کنید. قطعه کد زیر د. گروه پیش فرض به نام های web و api را نشان می دهد که از پیش درون فایل Kernel.php تعریف شده اند.