Russian (Pусский) translation by Masha Kolesnikova (you can also view the original English article)
В этой статье мы погрузимся глубоко внутрь Laravel, чтобы понять концепцию middleware. Первая половина статьи начинается с введения в middleware и для чего оно фактически используется.
По мере продвижения мы рассмотрим, как создать middleware в приложении Laravel. После создания вашего middleware мы рассмотрим доступные опции для регистрации в Laravel, чтобы его можно было фактически вызвать во время обработки запросов.
Я надеюсь, что вы считаете себя знакомым с основными концепциями Laravel и инструментом командной строки Artisan для генерации кода. Разумеется, рабочая установка последнего приложения Laravel позволяет сразу же запустить примеры, приведенные в этой статье.
Что такое middleware в Laravel?
Мы могли бы подумать о middleware как о механизме, позволяющем подключиться к типичному потоку обработки запросов приложения Laravel. Типичная обработка маршрута Laravel проходит через определенные этапы обработки запроса, а middleware - один из тех уровней, которым приложение должно пройти.
Итак, какова именно точка подключения к потоку обработки запроса Laravel? Подумайте о чем-то, что требует выполнения на ранних этапах начальной загрузки приложения. Например, на ранних стадиях необходимо аутентифицировать пользователей, чтобы решить, разрешено ли им доступ к текущему маршруту.
Несколько вещей, которые я мог бы подумать о том, что вы могли бы достичь с помощью middleware:
- логирование запросов
- перенаправление пользователей
- изменение / очистка входящих параметров
- манипулирование ответом, созданным приложением Laravel
- и многое другое
Фактически, приложение Laravel по умолчанию уже имеет пару важных компонентов middleware. Например, существует middleware, которое проверяет, находится ли сайт в режиме обслуживания. С другой стороны, существует middleware для очистки параметров запроса. Как я упоминал ранее, аутентификация пользователя также достигается самим middleware.
Я надеюсь, что объяснение пока поможет вам почувствовать себя более уверенно в терминах middleware. Если вы все еще смущены, не беспокойтесь об этом, так как мы собираемся создать middleware в следующем разделе, чтобы помочь вам точно понять, как можно использовать middleware в реальном мире.
Как создать middleware
В этом разделе мы создадим наше middleware. Но каково будет наше middleware?
Недавно я столкнулся с пользовательским требованием от моего клиента, что, если пользователи обращаются к сайту с любого мобильного устройства, они должны быть перенаправлены на соответствующий URL-адрес поддомена со всеми параметрами запроса. Я считаю, что это идеальный вариант использования, чтобы продемонстрировать, как middleware Laravel может использоваться в этом конкретном сценарии.
Причина, по которой мы хотели бы использовать middleware в этом случае, - это необходимость подключиться к потоку запросов приложения. В нашем middleware мы проверим агента пользователя и пользователи будут перенаправлены на соответствующий мобильный URL, если они используют мобильное устройство.
Обсудив всю эту теорию, давайте перейдем к коду, это лучший способ понять новую концепцию, не так ли?
Как разработчик Laravel, вы в конечном итоге используете команду artisan большую часть времени для генерации кода. Давайте используем его для создания базового кода шаблона для нашего middleware.
Перейдите в командную строку и перейдите в корень вашего проекта. Выполните следующую команду для создания middleware MobileRedirect.
1 |
php artisan make:middleware MobileRedirect |
И это должно создать файл app/Http/Middleware/MobileRedirect.php со следующим кодом.
1 |
<?php
|
2 |
|
3 |
namespace App\Http\Middleware; |
4 |
|
5 |
use Closure; |
6 |
|
7 |
class MobileRedirect |
8 |
{
|
9 |
/**
|
10 |
* Handle an incoming request.
|
11 |
*
|
12 |
* @param \Illuminate\Http\Request $request
|
13 |
* @param \Closure $next
|
14 |
* @return mixed
|
15 |
*/
|
16 |
public function handle($request, Closure $next) |
17 |
{
|
18 |
return $next($request); |
19 |
}
|
20 |
}
|
Чаще всего вы заметите реализацию метода handle, который выступает в качестве основы middleware, и основная логика middleware, которую вы хотите реализовать, должна идти здесь.
Позвольте мне воспользоваться этой возможностью, чтобы представить типы middleware, с которым связан Laravel. В основном, это два типа - middleware до и middleware после.
Как следует из названия, middleware до это то, что выполняется до того, как запрос фактически обработан, и ответ построен. С другой стороны, middleware после выполняются того, как запрос обрабатывается приложением, и ответ уже построен в это время.
В нашем случае нам необходимо перенаправить пользователя перед обработкой запроса, и, следовательно, это будет middleware до.
Идем дальше и модифицируем файл app/Http/Middleware/MobileRedirect.php со следующим содержимым.
1 |
<?php
|
2 |
|
3 |
namespace App\Http\Middleware; |
4 |
|
5 |
use Closure; |
6 |
|
7 |
class MobileRedirect |
8 |
{
|
9 |
/**
|
10 |
* Handle an incoming request.
|
11 |
*
|
12 |
* @param \Illuminate\Http\Request $request
|
13 |
* @param \Closure $next
|
14 |
* @return mixed
|
15 |
*/
|
16 |
public function handle($request, Closure $next) |
17 |
{
|
18 |
// check if the request is from mobile device
|
19 |
if ($request->mobile == "1") { |
20 |
return redirect('mobile-site-url-goes-here'); |
21 |
}
|
22 |
|
23 |
return $next($request); |
24 |
}
|
25 |
}
|
Для простоты мы просто проверяем наличие параметра mobile querystring, и если он установлен на TRUE, пользователь будет перенаправлен на соответствующий URL-адрес мобильного сайта. Конечно, вы хотели бы использовать библиотеку обнаружения пользовательского агента, если хотите обнаружить ее в режиме реального времени.
Кроме того, вы хотели бы заменить маршрут mobile-site-url-go-here правильным маршрутом или URL-адресом, поскольку это просто место для демонстрационных целей.
Следуя нашей пользовательской логике, есть вызов $next($request), который позволяет обрабатывать запрос далее в цепочке приложения. В нашем случае важно отметить, что мы поместили логику обнаружения мобильного устройства до вызова $next($request), эффективно сделав его middleware до.
На этом наше middleware почти готово к тестированию. На данный момент Laravel не знает о нашем middleware. Чтобы это произошло, вам необходимо зарегистрировать ваше middleware с помощью приложения Laravel, и это будет темой нашего следующего раздела.
Прежде чем перейти к следующему разделу, я хотел бы продемонстрировать, как выглядит middleware после, на случай, если вам будет любопытно.
1 |
<?php
|
2 |
|
3 |
namespace App\Http\Middleware; |
4 |
|
5 |
use Closure; |
6 |
|
7 |
class CustomMiddleWare |
8 |
{
|
9 |
/**
|
10 |
* Handle an incoming request.
|
11 |
*
|
12 |
* @param \Illuminate\Http\Request $request
|
13 |
* @param \Closure $next
|
14 |
* @return mixed
|
15 |
*/
|
16 |
public function handle($request, Closure $next) |
17 |
{
|
18 |
$response = $next($request); |
19 |
|
20 |
/* your custom logic goes here */
|
21 |
|
22 |
return $response; |
23 |
}
|
24 |
}
|
Как вы уже заметили, пользовательская логика middleware будет выполнена после того, как запрос будет обработан приложением Laravel. В это время у вас также есть доступ к объекту $response, который позволяет вам манипулировать определенными аспектами, если вы этого хотите.
Это было middleware после.
Наше пользовательское middleware в действии
В этом разделе описывается процесс регистрации middleware внутри приложения Laravel, чтобы он мог фактически быть вызван во время потока обработки запроса.
Откройте файл app/Http/Kernel.php и найдите следующий фрагмент.
1 |
/**
|
2 |
* The application's global HTTP middleware stack.
|
3 |
*
|
4 |
* These middleware are run during every request to your application.
|
5 |
*
|
6 |
* @var array
|
7 |
*/
|
8 |
protected $middleware = [ |
9 |
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, |
10 |
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, |
11 |
\App\Http\Middleware\TrimStrings::class, |
12 |
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, |
13 |
];
|
Как вы можете видеть, $middleware содержит массив из middleware, который поставляется с установкой по умолчанию Laravel. Перечисленное здесь middleware будет выполняться к каждому запросу Laravel, и, таким образом, это идеальный кандидат для размещения нашего собственного middleware.
Двигаемся дальше и включаем наше middleware, как показано в следующем фрагменте.
1 |
protected $middleware = [ |
2 |
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, |
3 |
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, |
4 |
\App\Http\Middleware\TrimStrings::class, |
5 |
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, |
6 |
\App\Http\Middleware\MobileRedirect::class, |
7 |
];
|
Теперь попробуйте получить доступ к любому из ваших маршрутов Laravel с помощью querystring mobile=1, и это должно вызвать наш код middleware!
Таким образом, вы должны зарегистрировать свое middleware, которое должно выполняться к каждому запросу. Однако иногда вы хотите запускать свое middleware только для определенных маршрутов. Давайте проверим, как это сделать, используя $routeMiddleware.
В контексте нашего текущего примера предположим, что пользователи будут перенаправлены на мобильный сайт, если они получат доступ к определенному маршруту на вашем сайте. В этом случае вам не нужно включать ваше middleware в список $middleware.
Вместо этого вам нужно подключить middleware непосредственно к определению маршрута, как показано ниже.
1 |
Route::get('/hello-world', 'HelloWorldController@index')->middleware(\App\Http\Middleware\MobileRedirect::class); |
Фактически, мы могли бы сделать еще один шаг и создать псевдоним для нашего middleware, чтобы вам не пришлось использовать встроенные имена классов.
Откройте файл app/Http/Kernel.php и найдите $routeMiddleware, который содержит сопоставления псевдонимов с middleware. Давайте включим нашу запись в этот список, как показано в следующем фрагменте.
1 |
protected $routeMiddleware = [ |
2 |
'auth' => \Illuminate\Auth\Middleware\Authenticate::class, |
3 |
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, |
4 |
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, |
5 |
'can' => \Illuminate\Auth\Middleware\Authorize::class, |
6 |
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, |
7 |
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, |
8 |
'mobile.redirect' => \App\Http\Middleware\MobileRedirect::class |
9 |
];
|
И пересмотренное определение маршрута выглядит так.
1 |
Route::get('/hello-world', 'HelloWorldController@index')->middleware('mobile.redirect'); |
На этом все. Это было довольно просто, не так ли?
Фактически, мы дошли до конца этой статьи, и я надеюсь, что вам это понравилось.
Заключение
Изучение архитектурной концепции в любых фреймворках - это всегда захватывающий материал, и именно это мы и сделали в этой статье, когда мы исследовали middleware Laravel.
Начиная с базового введения в middleware, мы переключили внимание на тему создания пользовательского middleware в приложении Laravel. И именно последняя половина статьи показала, как зарегистрировать ваше middleware в Laravel, и также возможность изучить различные способы, которыми вы могли бы подключить ваше middleware.
Надеюсь, путешествие было плодотворным, и статья помогла вам обогатить ваши знания. Кроме того, если вы хотите, чтобы я придумывал конкретные темы в следующих статьях, вы всегда можете рассказать мне об этом.
Вот и все на сегодня, и не стесняйтесь задавать свои запросы, если таковые имеются, используя фид ниже!



