Примечание: Хотите узнать больше о маршрутизации? Посмотрите страницу "почему фреймворк?" для более подробного объяснения.
Основная маршрутизация в Flight выполняется путем сопоставления шаблона URL с функцией обратного вызова или массивом класса и метода.
Flight::route('/', function(){ echo 'привет, мир!'; });
Маршруты сопоставляются в том порядке, в котором они определены. Первый сопоставленный маршрут будет вызван.
Обратный вызов может быть любым объектом, который можно вызывать. Так что вы можете использовать обычную функцию:
function hello() { echo 'привет, мир!'; } Flight::route('/', 'hello');
Вы также можете использовать статический метод класса:
class Greeting { public static function hello() { echo 'привет, мир!'; } } Flight::route('/', [ 'Greeting','hello' ]);
Или создав объект сначала, а затем вызвать метод:
// Greeting.php class Greeting { public function __construct() { $this->name = 'Иванов Иван'; } public function hello() { echo "Привет, {$this->name}!"; } } // index.php $greeting = new Greeting(); Flight::route('/', [ $greeting, 'hello' ]); // Вы также можете сделать это без предварительного создания объекта // Примечание: В конструктор не будут переданы аргументы Flight::route('/', [ 'Greeting', 'hello' ]); // Кроме того, вы можете использовать эту более короткую синтаксис Flight::route('/', 'Greeting->hello'); // или Flight::route('/', Greeting::class.'->hello');
Если вы хотите использовать внедрение зависимостей через контейнер (PSR-11, PHP-DI, Dice и т. д.), единственный тип маршрутов, где это доступно - это либо непосредственное создание объекта самостоятельно и использование контейнера для создания вашего объекта, или вы можете использовать строки для определения класса и метода для вызова. Загляните на страницу [Внедрение зависимостей] (/learn/extending) для более подробной информации.
Вот быстрый пример:
use flight\database\PdoWrapper; // Greeting.php class Greeting { protected PdoWrapper $pdoWrapper; public function __construct(PdoWrapper $pdoWrapper) { $this->pdoWrapper = $pdoWrapper; } public function hello(int $id) { // делаем что-то с $this->pdoWrapper $name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]); echo "Привет, мир! Меня зовут {$name}!"; } } // index.php // Настройте контейнер в соответствии с вашими потребностями // Смотрите страницу Внедрение зависимостей для более подробной информации о PSR-11 $dice = new \Dice\Dice(); // Не забудьте заново присвоить переменную '$dice = '!!!!! $dice = $dice->addRule('flight\database\PdoWrapper', [ 'shared' => true, 'constructParams' => [ 'mysql:host=localhost;dbname=test', 'root', 'password' ] ]); // Зарегистрируйте обработчик контейнера Flight::registerContainerHandler(function($class, $params) use ($dice) { return $dice->create($class, $params); }); // Маршруты как обычно Flight::route('/hello/@id', [ 'Greeting', 'hello' ]); // или Flight::route('/hello/@id', 'Greeting->hello'); // или Flight::route('/hello/@id', 'Greeting::hello'); Flight::start();
По умолчанию шаблоны маршрутов сопоставляются с каждым методом запроса. Вы можете отвечать на конкретные методы, поместив идентификатор перед URL.
Flight::route('GET /', function () { echo 'Получен запрос GET.'; }); Flight::route('POST /', function () { echo 'Получен запрос POST.'; }); // Невозможно использовать Flight::get() для маршрутов, так как это метод // для получения переменных, а не для создания маршрута. // Flight::post('/', function() { /* код */ }); // Flight::patch('/', function() { /* код */ }); // Flight::put('/', function() { /* код */ }); // Flight::delete('/', function() { /* код */ });
Вы также можете сопоставить несколько методов с одним обратным вызовом, используя разделитель |:
|
Flight::route('GET|POST /', function () { echo 'Получен запрос GET или POST.'; });
Кроме того, можно получить объект Router, который содержит некоторые вспомогательные методы для использования:
$router = Flight::router(); // картировка всех методов $router->map('/', function() { echo 'привет, мир!'; }); // GET запрос $router->get('/users', function() { echo 'пользователи'; }); // $router->post(); // $router->put(); // $router->delete(); // $router->patch();
Вы можете использовать регулярные выражения в ваших маршрутах:
Flight::route('/user/[0-9]+', function () { // Это соответствует /user/1234 });
Хотя это метод доступен, рекомендуется использовать именованные параметры или именованные параметры с регулярными выражениями, так как они более читаемы и легче поддерживать.
Вы можете указать именованные параметры в ваших маршрутах, которые будут переданы в вашу функцию обратного вызова.
Flight::route('/@name/@id', function (string $name, string $id) { echo "привет, $name ($id)!"; });
Вы также можете включать регулярные выражения с именованными параметрами, используя разделитель ::
:
Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { // Это соответствует /bob/123 // Но не соответствует /bob/12345 });
Примечание: Сопоставление групп regex () с именованными параметрами не поддерживается. :'(
()
Вы можете указать именованные параметры, которые являются необязательными для сопоставления путем обертывания сегментов в скобки.
Flight::route( '/blog(/@year(/@month(/@day)))', function(?string $year, ?string $month, ?string $day) { // Это соответствует следующим URL: // /blog/2012/12/10 // /blog/2012/12 // /blog/2012 // /blog } );
Любые несопоставленные необязательные параметры будут переданы как NULL.
NULL
Сопоставление выполняется только на отдельных сегментах URL. Если вы хотите сопоставить несколько сегментов, вы можете использовать спецсимвол *.
*
Flight::route('/blog/*', function () { // Это будет соответствовать /blog/2000/02/01 });
Для направления всех запросов на один обратный вызов, вы можете сделать следующее:
Flight::route('*', function () { // Что-то делаем });
Вы можете передать выполнение следующему сопоставленному маршруту, вернув true из вашей функции обратного вызова.
true
Flight::route('/user/@name', function (string $name) { // Проверяем некоторое условие if ($name !== "Боб") { // Продолжить к следующему маршруту return true; } }); Flight::route('/user/*', function () { // Это будет вызвано });
Вы можете назначить псевдоним маршруту, так чтобы URL можно было динамически генерировать позже в вашем коде (например, в шаблоне).
Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); // позже в коде Flight::getUrl('user_view', [ 'id' => 5 ]); // вернет '/users/5'
Это особенно полезно, если ваш URL случайно изменится. В предыдущем примере предположим, что пользователи были перемещены в /admin/users/@id вместо этого. С использованием псевдонима вам не нужно изменять места, где вы ссылаетесь на псевдоним, потому что псевдоним теперь вернет /admin/users/5, как в приведенном выше примере.
/admin/users/@id
/admin/users/5
Псевдоним маршрутизации по-прежнему работает в группах также:
Flight::group('/users', function() { Flight::route('/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); }); // позже в коде Flight::getUrl('user_view', [ 'id' => 5 ]); // вернет '/users/5'
Если вы хотите проверить информацию о сопоставленном маршруте, вы можете запросить объект маршрута, передав true в качестве третьего параметра в метод маршрута. Объект маршрута всегда будет последним параметром, переданным в вашу функцию обратного вызова.
Flight::route('/', function(\flight\net\Route $route) { // Массив сопоставленных методов HTTP $route->methods; // Массив именованных параметров $route->params; // Соответствующее регулярное выражение $route->regex; // Содержит содержимое любого '*', используемого в шаблоне URL $route->splat; // Показывает путь URL.... если вам действительно нужно $route->pattern; // Показывает, какое промежуточное ПО назначено этому $route->middleware; // Показывает псевдоним, назначенный этому маршруту $route->alias; }, true);
Иногда вам может потребоваться группировать связанные маршруты вместе (например, /api/v1). Вы можете сделать это, используя метод group:
/api/v1
group
Flight::group('/api/v1', function () { Flight::route('/users', function () { // Соответствует /api/v1/users }); Flight::route('/posts', function () { // Соответствует /api/v1/posts }); });
Вы можете даже вкладывать группы из групп:
Flight::group('/api', function () { Flight::group('/v1', function () { // Flight::get() получает переменные, он не устанавливает маршрут! Смотрите ниже контекст объекта Flight::route('GET /users', function () { // Соответствует GET /api/v1/users }); Flight::post('/posts', function () { // Соответствует POST /api/v1/posts }); Flight::put('/posts/1', function () { // Соответствует PUT /api/v1/posts }); }); Flight::group('/v2', function () { // Flight::get() получает переменные, он не устанавливает маршрут! Смотрите ниже контекст объекта Flight::route('GET /users', function () { // Соответствует GET /api/v2/users }); }); });
Вы все еще можете использовать группировку маршрутов с объектом Engine следующим образом:
Engine
$app = new \flight\Engine(); $app->group('/api/v1', function (Router $router) { // используйте переменную $router $router->get('/users', function () { // Соответствует GET /api/v1/users }); $router->post('/posts', function () { // Соответствует POST /api/v1/posts }); });
Теперь вы можете потоково отправлять ответы клиенту, используя метод streamWithHeaders(). Это полезно для отправки больших файлов, длительных процессов или генерации больших ответов. Потоковая передача маршрута обрабатывается немного по-другому, чем обычный маршрут.
streamWithHeaders()
Примечание: Передача ответов доступна только если у вас установлен параметр flight.v2.output_buffering в значение false.
flight.v2.output_buffering
Вы можете передавать ответ клиенту, используя метод stream() на маршруте. Если вы делаете так, вам необходимо установить все методы вручную перед тем, как что-то выводить в клиент. Это делается с помощью функции header() php или метода Flight::response()->setRealHeader().
stream()
header()
Flight::response()->setRealHeader()
Flight::route('/@filename', function($filename) { // очевидно, вы также будете очищать путь и прочее. $fileNameSafe = basename($filename); // Если у вас есть дополнительные заголовки для установки после выполнения маршрута // вы должны определить их, прежде чем что-то будет выведено. // Все они должны быть прямым вызовом функции header() или // вызовом метода Flight::response()->setRealHeader() header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); // или Flight::response()->setRealHeader('Content-Disposition', 'attachment; filename="'.$fileNameSafe.'"'); $fileData = file_get_contents('/some/path/to/files/'.$fileNameSafe); // Обработка ошибок и прочее if(empty($fileData)) { Flight::halt(404, 'Файл не найден'); } // вручную установить длину контента, если хотите header# Маршрутизация > **Примечание:** Хотите узнать больше о маршрутизации? Посмотрите страницу ["почему фреймворк?"](/learn/why-frameworks) для более подробного объяснения. Основная маршрутизация в Flight выполняется путем сопоставления шаблона URL с функцией обратного вызова или массивом класса и метода. ```php Flight::route('/', function(){ echo 'привет, мир!'; });