IO v7. Route и работа с ними
Описание
Route (класс маршрутов) - это обработчик URL ссылок (ранее controller). Здесь также используются вызовы class, api (ранее model) и template (ранее view). Route вызывается в браузере в строке URL.
Различные вариации URL называют маршрутами. В данной версии фреймворка автоматическая регистрация маршрутов невозможна по причине отделения backend от frontend и внедрения Vue3. Каждый маршрут нужно регистрировать вручную, но уже под любым именем и путем. Причем регистрировать нужно как сами маршруты, так и классы маршрутов (route). Маршруты регистрируются в классе маршрута, а классы маршрутов регистрируются в модуле (для проекта в файле project/src/app/Module.php, для модуля в файле project/modules/<modulename>/php/Module.php). При регистрации маршрутов можно использовать regexp выражения.
Содержимое файла
В проекте:
<?php
namespace App\Routes;
use IO\Route;
class ExampleRoute extends Route
{
/**
* Регистрация маршрутов
*/
public static function routes($app)
{
$app->add_route([
'type' => ['get', 'post'],
'url' => '/example',
'name' => 'app:example',
'method' => 'actionExample',
]);
}
/**
* Example маршрут
*/
public function actionExample()
{
return $this->render('@app/example.twig');
}
}
В модуле (например: trade):
<?php
namespace BMC\Trade\Routes;
use IO\Route;
class ExampleRoute extends Route
{
/**
* Регистрация маршрутов
*/
public static function routes($app)
{
$app->add_route([
'type' => ['get', 'post'],
'url' => '/trade/example',
'name' => 'trade:example',
'method' => 'actionExample',
]);
}
/**
* Example маршрут
*/
public function actionExample()
{
return $this->render('@trade/example.twig');
}
}
Route выше обрабатывает ссылку "site.kz/example".
Файлы route'ов проекта находятся в папке project/src/app/Routes, а модуля в папке project/modules/<modulename>/php/Routes. Имя файла должно начинаться с большой буквы и иметь постфикс Route.php (пример: ExampleRoute.php). Имя класса должно быть таким же, как и название файла, без формата файла .php (пример: ExampleRoute).
Регистрация классов маршрутов
Для того, чтобы маршруты были определены фреймворком и задействованы, их классы нужно регистрировать.
В проекте, регистрация классов маршрутов осуществляется в файле project/src/app/Module.php в функции init(), используя функцию $app->add_routes().
В модуле, регистрация классов маршрутов осуществляется в файле project/src/modules/<modulename>/php/Module.php в функции init(), используя функцию $app->add_routes().
public static function init($app)
{
// Регистрация маршрутов
$app->add_routes([
\App\Routes\TestRoute::class,
\App\Routes\DefaultRoute::class,
]);
}
В функции init() вызывается функция $app->add_routes(), в которой указывается массив регистрируемых классов маршрутов проекта.
Методы, обязательные для объявления
routes()
static routes(
object(IO\App) $app
): void
Данная функция позволяет регистрировать маршруты.
public static function routes($app)
{
$app->add_route([
'type' => ['get', 'post'],
'url' => '/example',
'name' => 'app:example',
'method' => 'actionExample',
]);
}
В данной функции вызывается функция $app->add_route(), в которой указывается один регистрируемый маршрут. Сколько регистрируется маршрутов, столько и будет вызовов этой функции с разными параметрами.
У функции $app->add_route() имеется один единственный и обязательный аргумент, в который обязательно передается массив параметров маршрута. Он содержит параметры:
| Параметр | Тип | Описание | Значение по умолчанию | Обязательный |
|---|---|---|---|---|
type | array | Массив разрешенных методов (GET, POST, PUT, DELETE, OPTIONS и др.) маршрута (пример: ['get'] если разрешен один, или ['get', 'post'] если разрешено несколько). | ['get'] | Нет |
url | string | Маршрут в виде строки (пример: '/news/:id/images', где :id это получаемый параметр). | Да, если не используется параметр match | |
match | string | Маршрут в виде regexp правила (пример: /\/news\/(?<id>.*)/i, где id это получаемый параметр). | Да, если не используется параметр url | |
name | string | Имя маршрута для использования в других участках проекта (пример: app:news:item:images). | Да | |
method | string | Название метода, обрабатывающего маршрут (пример: actionNewsItemImages). | Да | |
nosession | bool | Указывает фреймворку НЕ создавать сессию для этого роута. Это оптимизация для публичных эндпоинтов, которым не нужна авторизация. | false | Нет |
ВНИМАНИЕ
Параметры url и match использовать совместно нельзя, можно использовать что-то одно.
Методы, необязательные для объявления
actionName()
Метод, обрабатывающий маршрут. Все обработчики маршрутов пишутся по подобию данного метода, начиная с префикса action и далее через CamelCase.
ВНИМАНИЕ
Выход из метода обязательно должен сопросождаться оператором возврата (инструкцией) return.
public function actionName()
{
// $this->args['name'] будет работать если маршрут зарегистрировали с параметром:
// - url, где используется ':name'
// - match, где используется '<name>'
$name = $this->args['name'] ?? '';
return $this->render('@app/example.twig', [
'name' => $name,
]);
}
init()
Функция, выполняющаяся перед вызовом маршрута (в IO6 называлась run_pre()).
static init()
public static function init()
{
// ...
}
after()
Функция, выполняющаяся после вызова маршрута (в IO6 называлась run_post()).
static after()
public static function after()
{
// ...
}
Доступные методы
render()
render(
string $template,
array $params = [],
int $httpCode = 200
): \IO\Response
Отрисовывает указанный template файл, передавая в него параметры из $params, с автоматической установкой заголовка Content-Type: text/html.
| Аргумент функции | Тип | Описание | Обязательный |
|---|---|---|---|
$template | string | Путь к template файлу. | Да |
$params | array | Массив параметров, передаваемых в указанный template файл. | Нет |
$httpCode | int | Код состояния HTTP (см. список). | Нет |
В аргументе $path для того чтобы указать, откуда брать файл шаблона, в начале указывается переменная, начинающаяся со знака @ (например @app). Где app это название модуля, которое указывается в функции module_name() в файле:
project/src/app/Module.php- для проекта.project/src/modules/<modulename>/php/Module.php- для модуля.
Пример:
public function actionExample()
{
$name = xget('name');
$age = 25;
return $this->render('@app/example.twig', [
'name' => $name,
'age' => $age;
], 200);
}
json()
json(
array $params = [],
int $httpCode = 200
): \IO\Response
Возвращает JSON ответ, состоящий из переданных параметров $params, с автоматической установкой заголовка Content-Type: application/json.
| Аргумент функции | Тип | Описание | Обязательный |
|---|---|---|---|
$params | array | Массив параметров, для отображения в формате json. | Нет |
$httpCode | int | Код состояния HTTP (см. список). | Нет |
Пример:
public function actionExample1()
{
$name = xget('name');
$age = 25;
return $this->json([
'name' => $name,
'age' => $age;
], 200);
}
public function actionExample2()
{
$name = xget('name');
$age = 25;
// массив -> json
return [
'name' => $name,
'age' => $age;
];
}
text()
text(
string|int $content,
int $httpCode = 200
): \IO\Response
Возвращает простой текстовый ответ с заголовком Content-Type: text/plain.
| Аргумент функции | Тип | Описание | Обязательный |
|---|---|---|---|
$content | string|int | Текст, число. | Да |
$httpCode | int | Код состояния HTTP (см. список). | Нет |
Пример:
public function actionExample1()
{
return $this->text('hello world', 200);
}
public function actionExample2()
{
// текст -> text
return 'hello world';
}
public function actionExample3()
{
// html -> text
return '<h1>Hello World!</h1>';
}
public function actionExample4()
{
// число -> text
return 5; // "5"
}
public function actionExample5()
{
// boolean -> text
return true; // true -> "1", false -> ""
}
noContent()
noContent(
int $httpCode = 204
): \IO\Response
Возвращает пустой ответ без содержимого. Полезно для операций, которые не возвращают данных.
| Аргумент функции | Тип | Описание | Обязательный |
|---|---|---|---|
$httpCode | int | Код состояния HTTP (см. список). | Нет |
Пример:
public function actionExample1()
{
return $this->noContent(200);
}
public function actionExample2()
{
// null -> noContent
return null;
}
redirect()
redirect(
string $url,
int $httpCode = 302
): \IO\Response
Возвращает пустой ответ без содержимого. Полезно для операций, которые не возвращают данных.
| Аргумент функции | Тип | Описание | Обязательный |
|---|---|---|---|
$url | string | Ссылка (путь) для редиректа. | Да |
$httpCode | int | Код состояния HTTP (см. список). | Нет |
Пример:
public function actionExample()
{
return $this->noContent('/dashboard', 301);
}
Цепочки вызовов (Chaining)
Можно модифицировать ответ, вызывая методы после создания:
public function index()
{
return $this->json(['data' => 'value'])
->withHeader('X-Version', '1.0')
->withHeader('X-Processed-Time', time())
->withHeader('Cache-Control', 'no-cache');
}
public function withMultipleHeaders()
{
return $this->json(['success' => true])
->withHeaders([
'X-Version' => '2.0',
'X-Environment' => 'production',
'Cache-Control' => 'public, max-age=3600'
]);
}
public function conditionalHeaders()
{
$response = $this->render('@app/page.twig');
if ($this->request->isAjax())
{
$response->withHeader('X-Ajax', 'true');
}
return $response;
}
Данные запроса (Request)
Все роуты автоматически получают доступ к методам работы с запросами через объект $this->request и вспомогательные методы:
<?php
namespace App\Routes;
use IO\Route;
class UserRoute extends Route
{
public function actionCreate()
{
// Получить параметр из любого источника
$name = $this->request->input('name');
$email = $this->request->input('email');
// Получить все параметры
$all = $this->request->all();
// Получить только определенные поля
$data = $this->request->only(['name', 'email']);
// Исключить поля
$data = $this->request->except('password');
// Проверить наличие параметра
if ($this->request->has('name')) {
// ...
}
return $this->json(['success' => true]);
}
}
Подробная информация описана отдельной статьей о Request.
Middleware
Роуты поддерживают Middleware. Подробная информация описана отдельной статьей о Middleware.