Обработчики запросов

Главная содержательная часть в файле index.php — обработчик запроса:

<?php

$app = AppFactory::create();

// Обработчик
$app->get('/', function ($request, $response) {
    return $response->write('Welcome to Slim!');
});

Общий принцип работы любого веб-фреймворка отражает архитектуру HTTP. На каждый адрес задаётся обработчик (функция, handler), который выполняет необходимые действия и возвращает ответ. В Slim, все приложение (сайт) представлено объектом класса Slim\App. Этот объект содержит методы на каждый глагол HTTP: get, post, put и так далее. Эти методы принимают на вход два параметра, первый — адрес (говорят «маршрут»), для которого вызовется обработчик и второй, собственно сам обработчик. Лямбда-функция с двумя параметрами $request и $response.

Во фреймворках принято (и это соответствует идеям REST) определять маршрут, как комбинацию глагола HTTP и адреса. То есть GET /users и POST /users с точки зрения большинства фреймворков — разные маршруты со своими обработчиками. В этом достаточно просто убедиться, если определить соответствующие маршруты и выполнить к ним запросы с помощью curl.

<?php

$app = AppFactory::create();

$app->get('/users', function ($request, $response) {
    return $response->write('GET /users');
});

$app->post('/users', function ($request, $response) {
    return $response->write('POST /users');
});

$app->run();
$ curl localhost:8080/users
GET /users
$ curl -XPOST localhost:8080/users
POST /users

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

Первое, что бросается в глаза, у нас всего лишь один входной файл для всех адресов. Пользователь может запрашивать сколь угодно сложный адрес /companies/3/photos5, всё сведётся к запуску файла index.php, а сам адрес становится лишь значением $_SERVER['REQUEST_URI'].

.
├── site
│   └── public
│       └── index.php

Такой подход имеет название FrontController в противовес подходу, когда каждый адрес (на самом деле маршрут, но об этом чуть позже) фактически отображался на конкретный файл файловой системы. Такой подход называется PageController. В интернете до сих пор встречаются сайты построенные по этой модели, но она давным давно вышла из употребления. Заметить её легко, если вы видите адреса наподобие /users.php, то почти наверняка в корне сайта лежит файл users.php, отвечающий за обработку этой страницы.

.
├── site
│   └── public
│       └── home.php
│       └── users.php
│       └── companies.php

Во FrontController процесс поиска нужного обработчика называется диспетчеризацией, по аналогии с тем как это слово используется в оффлайн жизни. Пошагово он выглядит так:

До входа во фреймворк:

  1. Клиент выполняет запрос к веб-серверу расположенному на сервере. Кстати, клиент — это не обязательно браузер, в примере выше клиентом выступает программа curl.
  2. Веб-сервер перенаправляет запрос на index.php и устанавливает правильные параметры запроса.

После входа в сам PHP (именно это и есть диспетчеризация):

  1. Фреймворк анализирует параметры запроса и пытается сопоставить маршруты добавленные в объект $app (как в примерах в начале урока) с тем что пришло. Он сравнивает комбинацию глагола запроса и сам адрес. Этот процесс называется роутингом (или маршрутизацией). А место где внутри хранятся все добавленные маршруты обычно называют роутером.
  2. Если в процессе роутинга был найден соответствующий маршрут, то вызывается его обработчик.
  3. Ответ сформированный обработчиком отправляется обратно клиенту

Рассмотрим конкретный пример. Возьмём за основу следующий код:

<?php

$app = AppFactory::create();

$app->get('/', function ($request, $response) {
    return $response->write('GET /');
});

$app->get('/companies', function ($request, $response) {
    return $response->write('GET /companies');
});

$app->post('/companies', function ($request, $response) {
    return $response->write('POST /companies');
});

$app->run();

После запуска этого кода, формируется роутер, который содержит в себе три маршрута:

GET /
GET /companies
POST /companies

Теперь предположим, что клиент выполнил такой запрос:

$ curl -XPOST localhost:8080/companies

Веб-сервер запустил index.php, который проинициализировал объект $app (помните, что на каждый запрос этот процесс повторяется с нуля?), затем фреймворк сопоставил маршруты и нашёл, что за этот запрос отвечает POST /companies. Далее фреймворк вызвал обработчик, который вернул клиенту ответ: POST /companies.

Интересный вопрос заключается в том, что произойдёт, если фреймворк не обнаружит соответствия? Например, клиент запросит страницу /comments? В такой ситуации, фреймворк берёт управление на себя (по умолчанию) и автоматически отдаёт браузеру ответ 404, то есть говорит о том что страница не найдена. Всегда внимательно смотрите, какие делаются запросы и есть ли подходящие под них ответы, чтобы не мучатся вопросом "почему браузер ничего не показывает". Проще всего увидеть ответ от сервера через консоль разработчика вашего браузера:

DevTool Network

Она есть в каждом браузере. Попробуйте открыть её и понаблюдать за процессом загрузки.

Самостоятельная работа

  1. Добавьте обработчик в файл index.php, который мы создали в самостоятельной работе предыдущего урока:

    <?php
    
    $app->get('/users', function ($request, $response) {
        return $response->write('GET /users');
    });
    
  2. Откройте в браузере эту страницу. Убедитесь что на экран вывелся текст переданный в метод write().


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

  1. Front Controller

Для полного доступа к курсу, нужна профессиональная подписка

Профессиональная подписка откроет полный доступ ко всем курсам Хекслета, даст возможность обращаться за помощью к менторам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
115
курсов
892
упражнения
2241
час теории
3196
тестов

Зарегистрироваться

или войти в аккаунт

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг».

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг».