1. Code
  2. PHP
  3. Laravel

Понимание основ middleware Laravel

В этой статье мы погрузимся глубоко внутрь Laravel, чтобы понять концепцию middleware. Первая половина статьи начинается с введения в middleware и для чего оно фактически используется.
Scroll to top

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.

Надеюсь, путешествие было плодотворным, и статья помогла вам обогатить ваши знания. Кроме того, если вы хотите, чтобы я придумывал конкретные темы в следующих статьях, вы всегда можете рассказать мне об этом.

Вот и все на сегодня, и не стесняйтесь задавать свои запросы, если таковые имеются, используя фид ниже!