Архитектурная концепция Laravel: Жизненный цикл запроса

Источник: «Request Lifecycle»
Эта статья перевод страницы документации Laravel о жизненном цикле запроса и приложения обрабатывающего поступивший запрос от сервера.

Введение

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

Цель этого документа — дать обзор того, как работает фреймворк Laravel. Лучше познакомившись с общей структурой, всё кажется менее волшебным, и вы будете более уверенно создавать свои приложения. Если вы не понимаете сразу все термины, не отчаивайтесь! Просто попытайтесь получить общее представление о том что происходит, и ваши знания будут расти по мере изучения других разделов документации.

Обзор жизненного цикла

Первые шаги

Точкой входа всех запросов приложения Laravel является файл public/index.php. Все запросы направляются в этот файл конфигурацией вашего веб-сервера (Apache/Nginx). Файл index.php не содержит много кода. Скорее, это отправная точка для загрузки остальной части фреймворка.

Файл index.php загружает сгенерированное Composer определение автозагрузчика, а затем извлекает экземпляр приложения Laravel из bootstrap/app.php. Первое действие, предпринимаемое самим Laravel, — создание экземпляра приложения/сервис контейнера.

Узнать больше о Сервис Контейнер можно в статье Laravel: Сервис Контейнер — что нужно знать новичкам.

Ядра HTTP/Консоли

Затем входящий запрос отправляется либо в ядро HTTP, либо в ядро Console, в зависимости от типа запроса, поступившего в приложение. Эти два ядра служат центральной локацией, через которую проходят все запросы. А пока давайте просто сосредоточимся на ядре HTTP, которое находится в app/Http/Kernel.php

Ядро HTTP расширяет класс Illuminate\Foundation\Http\Kernel, определяющий массив bootstrappers — загрузчиков, которые будут выполняться перед выполнением запроса. Эти загрузчики настраивают обработку ошибок, настраивают логи, определяют среду/окружение приложения и выполняют другие задачи, которые необходимо выполнить до фактической обработки запроса. Обычно эти классы обрабатывают внутреннюю конфигурацию Laravel, о которой вам не нужно беспокоиться.

Ядро HTTP также определяет список HTTP middleware, через которые должны пройти все запросы, прежде чем они будут переданы приложению. Эти middleware обрабатывают чтение и запись HTTP сессии, определяют, находится ли приложение в режиме обслуживания, проверят CSRF токены и многое другое. Мы поговорим об этом подробнее в ближайшее время.

Что такое CSRF и зачем нужны CSRF токены вы можете узнать в статьях CSRF: Подделка межсайтовых запросов и CSRF: Как предотвратить уязвимость

Сигнатура метода дескриптора ядра HTTP довольно проста: он получает Request и возвращает Response. Думайте о ядре как о большом чёрном ящике, представляющем всё ваше Laravel приложение. Отправьте ему HTTP-запросы, и он вернёт HTTP-ответы.

Сервис Провайдеры

Одним из наиболее важных действий по начальной загрузке ядра является загрузка сервис провайдеров — поставщиков услуг вашего приложения. Сервис провайдеры несут ответственность за начальную загрузку различных компонентов фреймворка, таких, как базы данных, очередь, компоненты валидации и маршрутизации. Все сервис провайдеры приложения настраиваются в массиве providers конфигурационного файла config/app.php.

Laravel будет перебирать этот список провайдеров и создавать экземпляры каждого из них. После создания экземпляров провайдеров будет вызываться метод register всех провайдеров. Затем, как только все провайдеры будут зарегистрированы, для каждого провайдера будет вызван метод boot. Это сделано для того, чтобы сервис провайдеры могли зависеть от того, что каждая привязка контейнера будет зарегистрирована и доступна к моменту вызова метода boot.

По сути, каждая основная функция, предлагаемая Laravel, загружается и настраивается сервис провайдером. Поскольку они загружают и настраивают так много функций, предлагаемых фреймворком, сервис провайдеры являются важным аспектом всего процесса начальной загрузки Laravel.

Маршрутизация

Одним из наиболее важных сервис провайдеров в вашем Laravel приложении является App\Providers\RouteServiceProvider. Этот сервис провайдер загружает файлы маршрутов, содержащиеся в каталоге routes вашего приложения. Вперёд, откройте код RouteServiceProvide и посмотрите как он работает!

/app/Providers/RouteServiceProvider.php:

<?php

namespace App\Providers;

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;

class RouteServiceProvider extends ServiceProvider
{
/**
* The path to the "home" route for your application.
*
* Typically, users are redirected here after authentication.
*
* @var string
*/

public const HOME = '/home';

/**
* Define your route model bindings, pattern filters, and other route configuration.
*/

public function boot(): void
{
$this->configureRateLimiting();

$this->routes(function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));

Route::middleware('web')
->group(base_path('routes/web.php'));
});
}

/**
* Configure the rate limiters for the application.
*/

protected function configureRateLimiting(): void
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
}
}

После загрузки приложения и регистрации всех сервис провайдеров Request будет передан для обработки маршрутизатору. Маршрутизатор отправит запрос в маршрут или контроллер, а также запустит указанное middleware для данного маршрута.

Middleware предоставляет удобный механизм фильтрации и проверки HTTP-запросов, поступающих в ваше Laravel приложение. Например, Laravel включает middleware, проверяющее, аутентифицирован ли пользователь вашего приложения. Если пользователь не аутентифицирован, middleware перенаправит пользователя на страницу входа в приложение. Однако если пользователь аутентифицирован, middleware позволит запросу дальше обрабатываться в приложении. Некоторое middleware назначается всем маршрутам приложения, например, определённым в свойстве $middleware вашего HTTP ядра, а некоторые назначаются только определённым маршрутам или группам маршрутов. Узнать больше о middleware вы можете из полной документации по middleware](https://laravel.com/docs/10.x/middleware).

Если запрос проходит через всё middleware соответствующего маршрута, будет выполнен метод маршрута или контроллера, а ответ, возвращённый методом маршрута или контроллера, будет отправлен обратно через цепочку middleware.

Завершение

Как только метод маршрута или контроллера вернёт ответ. Ответ будет отправлен обратно через middleware, давая приложению возможность изменить или проверить исходящий ответ.

Наконец, когда ответ возвращается через middleware, метод handle ядра HTTP возвращает объект ответа, а файл index.php вызывает метод send для возвращённого ответа. Метод sand отправляет содержимое ответа в веб-браузер пользователя. Мы завершили наше путешествие по всему жизненному циклу запроса в Laravel!

Сосредоточьтесь на сервис провайдерах

Сервис провайдеры действительно являются ключом к начальной загрузке приложения Laravel. Экземпляр приложения создаётся, сервис провайдеры регистрируются, и запрос передаётся загруженному приложению. Это действительно так просто!

Чёткое понимание того, как приложение laravel создаётся и загружается через сервис провайдеров, очень ценно. Сервис провайдеры вашего приложения по умолчанию хранятся в каталоге app/Providers.

app/Providers/AppServiceProvider.php:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/

public function register(): void
{
//
}

/**
* Bootstrap any application services.
*/

public function boot(): void
{
//
}
}

По умолчанию AppServiceProvider практически пуст. Этот провайдер — отличное место для добавления собственных загрузочных и сервисных привязок вашего приложения. Для большинства приложений вы можете создать несколько сервис провайдеров, каждый из которых будет выполнять более точную загрузку определённых сервисов/служб, используемых вашим приложением.

Дополнительные материалы

Предыдущая Статья

Основы Laravel: Структура каталогов приложения

Следующая Статья

Laravel: Руководство по тестированию с Pest