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

Правила маршрутизации по умолчанию

Стандартное правило маршрутизации в Webman — это http://127.0.0.1:8787/{контроллер}/{действие}.

Стандартным контроллером является app\controller\IndexController, стандартным действием является index.

Например, для доступа:

  • http://127.0.0.1:8787 будет использован метод index класса app\controller\IndexController
  • http://127.0.0.1:8787/foo будет использован метод index класса app\controller\FooController
  • http://127.0.0.1:8787/foo/test будет использован метод test класса app\controller\FooController
  • http://127.0.0.1:8787/admin/foo/test будет использован метод test класса app\admin\controller\FooController (см. Много приложений)

С версии 1.4 Webman поддерживает более сложные правила маршрутизации по умолчанию, например:

app
├── admin
│   └── v1
│       └── v2
│           └── v3
│               └── controller
│                   └── IndexController.php
└── controller
    ├── v1
    │   └── IndexController.php
    └── v2
        └── v3
            └── IndexController.php

Если вы хотите изменить маршрут для определенного запроса, измените файл конфигурации config/route.php.

Если вы хотите отключить маршрутизацию по умолчанию, добавьте в последнюю строку файла конфигурации config/route.php следующую строку:

Route::disableDefaultRoute();

Закрытые маршруты

Добавьте следующий код маршрута в config/route.php:

use support\Request;
Route::any('/test', function (Request $request) {
    return response('test');
});

Внимание
Поскольку закрытая функция не принадлежит ни одному контроллеру, то $request->app, $request->controller и $request->action будут пустыми строками.

При обращении по адресу http://127.0.0.1:8787/test вернется строка test.

Внимание
Путь маршрута должен начинаться со знака /, например:

use support\Request;
// Неверный способ
Route::any('test', function (Request $request) {
    return response('test');
});

// Верный способ
Route::any('/test', function (Request $request) {
    return response('test');
});

Классовая маршрутизация

Добавьте следующий код маршрута в config/route.php:

Route::any('/testclass', [app\controller\IndexController::class, 'test']);

При обращении по адресу http://127.0.0.1:8787/testclass вернется значение метода test класса app\controller\IndexController.

Параметры маршрута

Если в маршруте есть параметры, они соответствуют "{key}", и результаты будут переданы в соответствующие параметры метода контроллера (начиная со второго параметра), например:

// Соответствует /user/123 /user/abc
Route::any('/user/{id}', [app\controller\UserController::class, 'get']);
namespace app\controller;
use support\Request;

class UserController
{
    public function get(Request $request, $id)
    {
        return response('Полученный параметр: '.$id);
    }
}

Больше примеров:

use support\Request;
// Соответствует /user/123, не соответствует /user/abc
Route::any('/user/{id:\d+}', function (Request $request, $id) {
    return response($id);
});

// Соответствует /user/foobar, не соответствует /user/foo/bar
Route::any('/user/{name}', function (Request $request, $name) {
   return response($name);
});

// Соответствует /user, /user/123 и /user/abc. [] обозначает опционально
Route::any('/user[/{name}]', function (Request $request, $name = null) {
   return response($name ?? 'tom');
});

// Соответствует любому запросу, начинающемуся с /user/
Route::any('/user/[{path:.+}]', function (Request $request) {
    return $request->path();
});

// Соответствует всем запросам options. После : укажите регулярное выражение, обозначающее правила для этого именованного параметра
Route::options('[{path:.+}]', function () {
    return response('');
});

Резюме расширенного использования

[] синтаксис в маршрутах Webman в основном используется для обработки опционных частей пути или совпадений с динамическими маршрутами, позволяя вам задавать более сложные структуры пути и правила соответствия.

: используется для указания регулярного выражения

Группы маршрутов

Иногда маршруты содержат множество одинаковых префиксов, и тогда мы можем использовать группы маршрутов для упрощения определения. Например:

Route::group('/blog', function () {
   Route::any('/create', function (Request $request) {return response('create');});
   Route::any('/edit', function (Request $request) {return response('edit');});
   Route::any('/view/{id}', function (Request $request, $id) {return response("view $id");});
});

Эквивалентно

Route::any('/blog/create', function (Request $request) {return response('create');});
Route::any('/blog/edit', function (Request $request) {return response('edit');});
Route::any('/blog/view/{id}', function (Request $request, $id) {return response("view $id");});

Вложенное использование group

Route::group('/blog', function () {
   Route::group('/v1', function () {
      Route::any('/create', function (Request $request) {return response('create');});
      Route::any('/edit', function (Request $request) {return response('edit');});
      Route::any('/view/{id}', function (Request $request, $id) {return response("view $id");});
   });  
});

Промежуточные маршруты

Мы можем установить промежуточное программное обеспечение для одного маршрута или группы маршрутов.
Например:

Route::any('/admin', [app\admin\controller\IndexController::class, 'index'])->middleware([
    app\middleware\MiddlewareA::class,
    app\middleware\MiddlewareB::class,
]);

Route::group('/blog', function () {
   Route::any('/create', function () {return response('create');});
   Route::any('/edit', function () {return response('edit');});
   Route::any('/view/{id}', function ($request, $id) {response("view $id");});
})->middleware([
    app\middleware\MiddlewareA::class,
    app\middleware\MiddlewareB::class,
]);
# Неправильный пример использования (это использование корректно только при webman-framework >= 1.5.7)
Route::group('/blog', function () {
   Route::group('/v1', function () {
      Route::any('/create', function (Request $request) {return response('create');});
      Route::any('/edit', function (Request $request) {return response('edit');});
      Route::any('/view/{id}', function (Request $request, $id) {return response("view $id");});
   });  
})->middleware([
    app\middleware\MiddlewareA::class,
    app\middleware\MiddlewareB::class,
]);
# Правильный пример использования
Route::group('/blog', function () {
   Route::group('/v1', function () {
      Route::any('/create', function (Request $request) {return response('create');});
      Route::any('/edit', function (Request $request) {return response('edit');});
      Route::any('/view/{id}', function (Request $request, $id) {return response("view $id");});
   })->middleware([
        app\middleware\MiddlewareA::class,
        app\middleware\MiddlewareB::class,
    ]);  
});

Ресурсные маршруты

Route::resource('/test', app\controller\IndexController::class);

// Указать ресурсные маршруты
Route::resource('/test', app\controller\IndexController::class, ['index','create']);

// Непредусмотренные ресурсные маршруты
// Например, сообщение о доступе будет с адресом any маршрута /test/notify или /test/notify/{id}, routeName будет test.notify
Route::resource('/test', app\controller\IndexController::class, ['index','create','notify']);
Глагол URI Действие Имя маршрута
GET /test index test.index
GET /test/create create test.create
POST /test store test.store
GET /test/{id} show test.show
GET /test/{id}/edit edit test.edit
PUT /test/{id} update test.update
DELETE /test/{id} destroy test.destroy
PUT /test/{id}/recovery recovery test.recovery

Генерация URL

Внимание
Временно не поддерживается генерация URL для вложенных групп маршрутов

Например, маршрут:

Route::any('/blog/{id}', [app\controller\BlogController::class, 'view'])->name('blog.view');

Мы можем использовать следующий метод для генерации этого маршрута URL.

route('blog.view', ['id' => 100]); // Результат: /blog/100

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

Получение информации о маршруте

С помощью объекта $request->route мы можем получить информацию о текущем маршруте запроса, например:

$route = $request->route; // Эквивалентно $route = request()->route;
if ($route) {
    var_export($route->getPath());
    var_export($route->getMethods());
    var_export($route->getName());
    var_export($route->getMiddleware());
    var_export($route->getCallback());
    var_export($route->param());
}

Внимание
Если текущий запрос не соответствует ни одному маршруту, настроенному в config/route.php, то $request->route будет равен null. То есть при использовании маршрутизации по умолчанию $request->route будет равен null.

Обработка 404

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

Если разработчик хочет вмешаться в бизнес-процесс, когда маршрут не найден, он может использовать предоставленный Webman метод fallback для маршрута Route::fallback($callback). Например, следующий фрагмент кода перенаправит на главную страницу, если маршрут не найден.

Route::fallback(function(){
    return redirect('/');
});

Также, когда маршрут не существует, можно вернуть JSON-данные, что очень полезно, когда Webman используется в качестве API.

Route::fallback(function(){
    return json(['code' => 404, 'msg' => '404 не найдено']);
});

Добавление промежуточного ПО для 404

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

Route::fallback(function(){
    return json(['code' => 404, 'msg' => '404 не найдено']);
})->middleware([
    app\middleware\MiddlewareA::class,
    app\middleware\MiddlewareB::class,
]);

Связанные ссылки Пользовательская 404 500 страница

Отключение маршрутизации по умолчанию

// Отключение стандартной маршрутизации основного приложения, без влияния на плагины приложений
Route::disableDefaultRoute();
// Отключение маршрутизации приложений администраторов основного проекта, без влияния на плагины приложений
Route::disableDefaultRoute('', 'admin');
// Отключение стандартной маршрутизации плагина foo, без влияния на основное приложение
Route::disableDefaultRoute('foo');
// Отключение стандартной маршрутизации администраторского приложения плагина foo, без влияния на основное приложение
Route::disableDefaultRoute('foo', 'admin');
// Отключение стандартной маршрутизации контроллера [\app\controller\IndexController::class, 'index']
Route::disableDefaultRoute([\app\controller\IndexController::class, 'index']);

Аннотации для отключения маршрутизации по умолчанию

Мы можем отключить стандартную маршрутизацию для определенного контроллера с помощью аннотации, например:

namespace app\controller;
use support\annotation\DisableDefaultRoute;

#[DisableDefaultRoute]
class IndexController
{
    public function index()
    {
        return 'index';
    }
}

Аналогично, мы можем отключить стандартную маршрутизацию для определенного контроллера с помощью аннотации следующим образом:

namespace app\controller;
use support\annotation\DisableDefaultRoute;

class IndexController
{
    #[DisableDefaultRoute]
    public function index()
    {
        return 'index';
    }
}

Интерфейс маршрутизации

// Установить маршрут для обращения к $uri с любым методом
Route::any($uri, $callback);
// Установить маршрут для обращения к $uri с методом GET
Route::get($uri, $callback);
// Установить маршрут для обращения к $uri с методом POST
Route::post($uri, $callback);
// Установить маршрут для обращения к $uri с методом PUT
Route::put($uri, $callback);
// Установить маршрут для обращения к $uri с методом PATCH
Route::patch($uri, $callback);
// Установить маршрут для обращения к $uri с методом DELETE
Route::delete($uri, $callback);
// Установить маршрут для обращения к $uri с методом HEAD
Route::head($uri, $callback);
// Установить маршрут для обращения к $uri с методом OPTIONS
Route::options($uri, $callback);
// Одновременно установить маршруты для нескольких типов запросов
Route::add(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'], $uri, $callback);
// Группировка маршрутов
Route::group($path, $callback);
// Ресурсные маршруты
Route::resource($path, $callback, [$options]);
// Отключение маршрутизации
Route::disableDefaultRoute($plugin = '');
// Резервный маршрут, установка маршрута по умолчанию
Route::fallback($callback, $plugin = '');
// Получение всей информации о маршрутах
Route::getRoutes();

Если uri не имеет соответствующего маршрута (включая маршруты по умолчанию), и резервный маршрут также не установлен, вернется 404.

Несколько файлов конфигурации маршрутов

Если вы хотите использовать несколько файлов конфигурации маршрутов для управления ими, например, в случае с многими приложениями, где каждое приложение имеет свою конфигурацию маршрутов, то можно загрузить внешние файлы конфигурации маршрутов с помощью require.
Например, в config/route.php:

<?php

// Загрузка конфигурации маршрутов приложения admin
require_once app_path('admin/config/route.php');
// Загрузка конфигурации маршрутов приложения api
require_once app_path('api/config/route.php');