Маршрутизация URI
- Настройка собственных правил маршрутизации
- Заполнители
- Примеры
- Пользовательские заполнители
- Регулярные выражения
- Замыкания
- Сопоставление нескольких маршрутов
- Перенаправление маршрутов
- Группировка маршрутов
- Ограничения среды
- Обратная маршрутизация
- Использование именованных маршрутов
- Использование HTTP-глаголов в маршрутах
- Маршруты только для командной строки
- Глобальные параметры
- Параметры конфигурации маршрутов
Обычно существует взаимно-однозначное соответствие между строкой URL и соответствующим классом/методом контроллера. Сегменты в URI обычно следуют этому шаблону:
example.com/class/method/id/
В некоторых случаях, однако, вам может потребоваться переназначить это соответствие, чтобы вместо него вызывался другой класс/метод.
Например, предположим, что вы хотите, чтобы ваши URL имели такой прототип:
example.com/product/1/ example.com/product/2/ example.com/product/3/ example.com/product/4/
Обычно второй сегмент URL зарезервирован для имени метода, но в приведенном выше примере он вместо этого содержит идентификатор продукта. Чтобы решить эту проблему, CodeIgniter позволяет вам переназначить обработчик URI.
Настройка собственных правил маршрутизации
Правила маршрутизации определяются в файле app/Config/Routes.php. В нем вы увидите, что он создает экземпляр класса RouteCollection, который позволяет вам указать собственные критерии маршрутизации. Маршруты можно указывать с помощью заполнителей или регулярных выражений.
Маршрут просто принимает URI слева и сопоставляет его с контроллером и методом справа, а также с любыми параметрами, которые должны быть переданы контроллеру. Контроллер и метод должны быть указаны так же, как вы используете статический метод, разделяя полностью квалифицированный класс и его метод двоеточием, как Users::list. Если этому методу нужно передать параметры, то они будут указаны после имени метода, разделенные слешами:
// Calls the $Users->list() Users::list // Calls $Users->list(1, 23) Users::list/1/23
Заполнители
Типичный маршрут может выглядеть так:
$routes->add('product/(:num)', 'App\Catalog::productLookup');
В маршруте первый параметр содержит URI для сопоставления, а второй — конечную точку перенаправления. В приведенном выше примере, если в первом сегменте URL встречается буквальное слово «product», а во втором — число, то вместо этого используется класс «AppCatalog» и метод «productLookup».
Заполнители — это просто строки, которые представляют шаблон регулярного выражения. Во время процесса маршрутизации эти заполнители заменяются значением регулярного выражения. Они в основном используются для повышения читабельности.
Для использования в ваших маршрутах доступны следующие заполнители:
| Заполнители | Описание |
|---|---|
| (:any) | сопоставит все символы с этого момента до конца URI. Это может включать несколько сегментов URI. |
| (:segment) | сопоставит любой символ, кроме слеша (/), ограничивая результат одним сегментом. |
| (:num) | сопоставит любое целое число. |
| (:alpha) | сопоставит любую строку символов |
| (:alphanum) | сопоставит любую строку символов или целых чисел, или любую комбинацию двух. |
| (:hash) | аналогично (:segment), но может быть использован для наглядного определения маршрутов с хешированными идентификаторами. |
Примечание
{locale} не может использоваться в качестве заполнителя или другой части маршрута, так как он зарезервирован для использования в локализации.
Примеры
Вот несколько основных примеров маршрутизации.
URL, содержащий слово «journals» в первом сегменте, будет переназначен на класс «AppBlogs» и по умолчанию метод, который обычно index():
$routes->add('journals', 'App\Blogs');
URL, содержащий сегменты «blog/joe», будет переназначен на класс «Blogs» и метод «users». Идентификатор будет установлен в «34»:
$routes->add('blog/joe', 'Blogs::users/34');
URL с «product» в качестве первого сегмента и любым значением во втором будет переназначен на класс «Catalog» и метод «productLookup»:
$routes->add('product/(:any)', 'Catalog::productLookup');
URL с «product» в качестве первого сегмента и числом во втором будет переназначен на класс «Catalog» и метод «productLookupByID», передавая сопоставленное значение в качестве переменной методу:
$routes->add('product/(:num)', 'Catalog::productLookupByID/$1');
Обратите внимание, что единственный (:any) будет соответствовать нескольким сегментам в URL, если они присутствуют. Например, маршрут:
$routes->add('product/(:any)', 'Catalog::productLookup/$1');
будет соответствовать product/123, product/123/456, product/123/456/789 и т. д. Реализация в контроллере должна учитывать максимальное количество параметров:
public function productLookup($seg1 = false, $seg2 = false, $seg3 = false) {
echo $seg1; // Will be 123 in all examples
echo $seg2; // false in first, 456 in second and third example
echo $seg3; // false in first and second, 789 in third
}
Если соответствие нескольким сегментам не является желаемым поведением, (:segment) следует использовать при определении маршрутов. Для примеров URL выше:
$routes->add('product/(:segment)', 'Catalog::productLookup/$1');
будут соответствовать только product/123 и генерировать ошибки 404 для других примеров.
Предупреждение
Хотя метод add() удобен, рекомендуется всегда использовать маршруты на основе HTTP-глаголов, описанных ниже, так как это более безопасно. Если вы используете защиту CSRF, она не защищает запросы GET. Если URI, указанный в методе add() доступен через метод GET, защита CSRF не сработает.
Примечание
Использование маршрутов на основе HTTP-глаголов также обеспечит небольшое повышение производительности, так как хранятся только маршруты, соответствующие текущему методу запроса, что приводит к меньшему количеству маршрутов для сканирования при поиске соответствия.
Пользовательские заполнители
Вы можете создавать свои собственные заполнители, которые могут использоваться в вашем файле маршрутов, чтобы полностью настроить опыт и читабельность.
Вы добавляете новые заполнители с помощью метода addPlaceholder. Первый параметр — это строка, которая будет использоваться в качестве заполнителя. Второй параметр — шаблон регулярного выражения, которым он должен быть заменён. Это должно быть выполнено до добавления маршрута:
$routes->addPlaceholder('uuid', '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}');
$routes->add('users/(:uuid)', 'Users::show/$1');
Регулярные выражения
Если вы предпочитаете, вы можете использовать регулярные выражения для определения правил маршрутизации. Разрешены любые допустимые регулярные выражения, а также обратные ссылки.
Важно
Обратите внимание: если вы используете обратные ссылки, вы должны использовать синтаксис доллара вместо двойного обратного слеша. Типичный маршрут RegEx может выглядеть так:
$routes->add('products/([a-z]+)/(\d+)', 'Products::show/$1/id_$2');
В приведенном выше примере URI, подобный products/shirts/123, вместо этого вызовет метод show класса-контроллера Products, с оригинальными первым и вторым сегментами, переданными в качестве аргументов ему.
С помощью регулярных выражений вы также можете поймать сегмент, содержащий слеш (’/’), который обычно представляет разделитель между несколькими сегментами.
Например, если пользователь получает доступ к защищенной паролем части вашего веб-приложения, и вы хотите перенаправить его на ту же страницу после входа в систему, вам может пригодиться этот пример:
$routes->add('login/(.+)', 'Auth::login/$1');
Для тех из вас, кто не знаком с регулярными выражениями и хочет узнать больше о них, regular-expressions.info может стать хорошей отправной точкой.
Важно
Примечание: Вы также можете смешивать и сопоставлять шаблоны с регулярными выражениями.
Замыкания
Вы можете использовать анонимную функцию или замыкание в качестве конечной точки, к которой сопоставляется маршрут. Эта функция будет выполняться при посещении пользователем этого URI. Это удобно для быстрого выполнения небольших задач или даже просто для отображения простого представления:
$routes->add('feed', function () {
$rss = new RSSFeeder();
return $rss->feed('general');
});
Сопоставление нескольких маршрутов
Хотя метод add() прост в использовании, часто удобнее работать с несколькими маршрутами одновременно, используя метод map(). Вместо вызова метода add() для каждого маршрута, который вам нужно добавить, вы можете определить массив маршрутов и передать его в качестве первого параметра методу map():
$routes = []; $routes['product/(:num)'] = 'Catalog::productLookupById'; $routes['product/(:alphanum)'] = 'Catalog::productLookupByName'; $collection->map($routes);
Перенаправление маршрутов
Любой сайт, проживший достаточно долго, неизбежно столкнётся с перемещениями страниц. Вы можете указать маршруты, которые должны перенаправлять на другие маршруты, с помощью метода addRedirect(). Первый параметр — шаблон URI для старого маршрута. Второй параметр — либо новый URI для перенаправления, либо имя именованного маршрута. Третий параметр — код HTTP-статуса, который должен быть отправлен вместе с перенаправлением. Значение по умолчанию — 302, что представляет собой временное перенаправление, которое рекомендуется в большинстве случаев:
$routes->add('users/profile', 'Users::profile', ['as' => 'profile']);
// Redirect to a named route
$routes->addRedirect('users/about', 'profile');
// Redirect to a URI
$routes->addRedirect('users/about', 'users/profile');
Если маршрут перенаправления совпадает во время загрузки страницы, пользователь будет немедленно перенаправлен на новую страницу, прежде чем контроллер сможет загрузиться.
Группирование маршрутов
Вы можете сгруппировать свои маршруты под общим именем с помощью метода group(). Имя группы становится сегментом, который появляется перед маршрутами, определёнными внутри группы. Это позволяет уменьшить количество набираемого текста для создания обширного набора маршрутов, которые все разделяют открывающую строку, например, при создании административной области:
$routes->group('admin', function ($routes) {
$routes->add('users', 'Admin\Users::index');
$routes->add('blog', 'Admin\Blog::index');
});
Это добавит префикс «admin» к URI «users» и «blog», обрабатывая URL-адреса, такие как /admin/users и /admin/blog.
Если вам нужно назначить параметры группе, такие как пространство имён, сделайте это перед обратным вызовом:
$routes->group('api', ['namespace' => 'App\API\v1'], function ($routes) {
$routes->resource('users');
});
Это обработает маршрут ресурса для контроллера App\API\v1\Users с URI /api/users.
Вы также можете использовать определённый фильтр для группы маршрутов. Это всегда будет выполнять фильтр до или после контроллера. Это особенно полезно во время аутентификации или ведения журнала API:
$routes->group('api', ['filter' => 'api-auth'], function ($routes) {
$routes->resource('users');
});
Значение фильтра должно соответствовать одному из псевдонимов, определённых в app/Config/Filters.php.
При необходимости можно вкладывать группы в группы для более тонкой организации:
$routes->group('admin', function ($routes) {
$routes->group('users', function ($routes) {
$routes->add('list', 'Admin\Users::list');
});
});
Это обработает URL по адресу admin/users/list. Обратите внимание, что параметры, переданные во внешнюю group() (например, namespace и filter ), не объединяются с внутренними group() параметрами.
В какой-то момент вам может потребоваться сгруппировать маршруты для применения фильтров или других параметров конфигурации маршрута, таких как пространство имён, поддомен и т. д. Без необходимости добавлять префикс к группе вы можете передать пустую строку вместо префикса, и маршруты в группе будут маршрутизироваться так, как если бы группы никогда не существовало, но с заданными параметрами конфигурации маршрута.
Ограничения среды
Вы можете создать набор маршрутов, которые будут доступны только в определённой среде. Это позволяет создавать инструменты, доступные только разработчику на его локальных машинах, недоступные на тестовых или производственных серверах. Это можно сделать с помощью метода environment() . Первый параметр — имя среды. Любые маршруты, определённые в этом замыкании, доступны только из данной среды:
$routes->environment('development', function ($routes) {
$routes->add('builder', 'Tools\Builder::index');
});
Обратный маршрутизация
Обратный маршрут позволяет определить контроллер и метод, а также любые параметры, которые должен содержать ссылка, и заставить маршрутизатор найти соответствующий маршрут. Это позволяет изменять определения маршрутов без необходимости обновления кода вашего приложения. Обычно используется в представлениях для создания ссылок.
Например, если у вас есть маршрут к фотогалерее, к которой вы хотите создать ссылку, вы можете использовать вспомогательную функцию route_to() для получения текущего маршрута, который должен использоваться. Первый параметр — полное имя контроллера и метода, разделённые двоеточием (::), как и вы бы использовали при написании исходного маршрута. Любые параметры, которые необходимо передать в маршрут, передаются далее:
// The route is defined as:
$routes->add('users/(:num)/gallery(:any)', 'App\Controllers\Galleries::showUserGallery/$1/$2');
// Generate the relative URL to link to user ID 15, gallery 12
// Generates: /users/15/gallery/12
<a href="<?= route_to('App\Controllers\Galleries::showUserGallery', 15, 12) ?>">View Gallery</a>
Использование именованных маршрутов
Вы можете называть маршруты, чтобы сделать ваше приложение менее хрупким. Это присваивает имя маршруту, которое можно вызвать позже, и даже если определение маршрута изменится, все ссылки в вашем приложении, созданные с помощью route_to , по-прежнему будут работать без необходимости вносить какие-либо изменения с вашей стороны. Маршрут называется путём передачи параметра as с именем маршрута:
// The route is defined as:
$routes->add('users/(:num)/gallery(:any)', 'Galleries::showUserGallery/$1/$2', ['as' => 'user_gallery']);
// Generate the relative URL to link to user ID 15, gallery 12
// Generates: /users/15/gallery/12
<a href="<?= route_to('user_gallery', 15, 12) ?>">View Gallery</a>
Это также повышает читабельность представлений.
Использование HTTP-глаголов в маршрутах
Можно использовать HTTP-глаголы (метод запроса) для определения правил маршрутизации. Это особенно полезно при создании RESTful-приложений. Вы можете использовать любые стандартные HTTP-глаголы (GET, POST, PUT, DELETE и т. д.). Каждый глагол имеет свой собственный метод, который вы можете использовать:
$routes->get('products', 'Product::feature');
$routes->post('products', 'Product::feature');
$routes->put('products/(:num)', 'Product::feature');
$routes->delete('products/(:num)', 'Product::feature');
Вы можете указать несколько глаголов, которым должен соответствовать маршрут, передав их в качестве массива в метод match:
$routes->match(['get', 'put'], 'products', 'Product::feature');
Маршруты, доступные только из командной строки
Вы можете создать маршруты, которые работают только из командной строки и недоступны в веб-браузере, с помощью метода cli(). Это идеально подходит для создания задач cron или инструментов, используемых только в командной строке. Любой маршрут, созданный с помощью методов на основе HTTP-глаголов, также будет недоступен из командной строки, но маршруты, созданные с помощью метода any() , по-прежнему будут доступны из командной строки:
$routes->cli('migrate', 'App\Database::migrate');
Глобальные параметры
Все методы для создания маршрута (add, get, post, resource и т. д.) могут принимать массив параметров, которые могут изменять сгенерированные маршруты или дополнительно их ограничивать. Массив $options всегда является последним параметром:
$routes->add('from', 'to', $options);
$routes->get('from', 'to', $options);
$routes->post('from', 'to', $options);
$routes->put('from', 'to', $options);
$routes->head('from', 'to', $options);
$routes->options('from', 'to', $options);
$routes->delete('from', 'to', $options);
$routes->patch('from', 'to', $options);
$routes->match(['get', 'put'], 'from', 'to', $options);
$routes->resource('photos', $options);
$routes->map($array, $options);
$routes->group('name', $options, function ());
Применение фильтров
Вы можете изменить поведение определённых маршрутов, указав фильтры, которые будут выполняться до или после контроллера. Это особенно полезно во время аутентификации или ведения журнала API. Значение фильтра может быть строкой или массивом строк:
- соответствующих псевдонимам, определённым в app/Config/Filters.php.
- именам классов фильтров
Дополнительную информацию о настройке фильтров см. в разделе Фильтры контроллеров.
Предупреждение
Если вы задаёте фильтры для маршрутов в app/Config/Routes.php (не в app/Config/Filters.php), рекомендуется отключить автоматическую маршрутизацию. При включённой автоматической маршрутизации возможно, что к контроллеру можно получить доступ через URL, отличный от настроенного маршрута, в этом случае заданный вами для маршрута фильтр не будет применён. См. Использовать только определённые маршруты, чтобы отключить автоматическую маршрутизацию.
Фильтр псевдонима
Вы указываете псевдоним, определённый в app/Config/Filters.php, для значения фильтра:
$routes->add('admin',' AdminController::index', ['filter' => 'admin-auth']);
Вы также можете передать аргументы, которые будут переданы методам before() и after() фильтра псевдонима:
$routes->add('users/delete/(:segment)', 'AdminController::index', ['filter' => 'admin-auth:dual,noreturn']);
Фильтр имени класса
Вы указываете имя класса фильтра для значения фильтра:
$routes->add('admin',' AdminController::index', ['filter' => \App\Filters\SomeFilter::class]);
Несколько фильтров
Важно
Несколько фильтров по умолчанию отключены. Это из-за нарушения обратной совместимости. Если вы хотите его использовать, вам нужно настроить его. Подробности см. в разделе Несколько фильтров для маршрута в Обновление с 4.1.4 до 4.1.5.
Вы указываете массив для значения фильтра:
$routes->add('admin',' AdminController::index', ['filter' => ['admin-auth', \App\Filters\SomeFilter::class]]);
Назначение пространства имён
Хотя к сгенерированным контроллерам будет добавлен префикс по умолчанию (см. ниже), вы также можете указать другое пространство имён, которое будет использоваться в любом массиве параметров, с помощью параметра namespace. Значение должно быть пространством имён, которое вы хотите изменить:
// Routes to \Admin\Users::index()
$routes->add('admin/users', 'Users::index', ['namespace' => 'Admin']);
Новое пространство имён применяется только во время этого вызова для любых методов, создающих отдельный маршрут, таких как get, post и т. д. Для методов, создающих несколько маршрутов, новое пространство имён прикрепляется ко всем маршрутам, сгенерированным этой функцией, или, в случае group(), ко всем маршрутам, сгенерированным в ходе выполнения замыкания.
Ограничение до хоста
Вы можете ограничить группы маршрутов для работы только на определённом домене или поддоменах вашего приложения, передав параметр «hostname» вместе с нужным доменным именем в качестве части массива параметров:
$collection->get('from', 'to', ['hostname' => 'accounts.example.com']);
В этом примере указанные хосты будут работать только в том случае, если домен точно совпадает с «accounts.example.com». Он не будет работать на основном сайте «example.com».
Ограничение до поддоменов
Когда параметр subdomain присутствует, система будет ограничивать маршруты, чтобы они были доступны только на этом поддомене. Маршрут будет соответствовать только в том случае, если поддомен — тот, через который просматривается приложение:
// Limit to media.example.com
$routes->add('from', 'to', ['subdomain' => 'media']);
Вы можете ограничить его любым поддоменом, установив значение на звёздочку (*). Если вы просматриваете URL без поддомена, это не будет соответствовать:
// Limit to any sub-domain
$routes->add('from', 'to', ['subdomain' => '*']);
Важно
Система не идеальна и должна быть протестирована для вашего конкретного домена перед использованием в рабочей среде. Большинство доменов должны работать нормально, но некоторые крайние случаи, особенно с точкой в самом домене (не используемая для разделения суффиксов или www), могут потенциально привести к ложным срабатываниям.
Сдвиг сопоставленных параметров
Вы можете сдвинуть сопоставленные параметры в вашем маршруте на любое числовое значение с помощью параметра offset со значением, равным количеству смещаемых сегментов.
Это может быть полезно при разработке API с номером версии в первом сегменте URI. Также может использоваться, когда первый параметр — строка языка:
$routes->get('users/(:num)', 'users/show/$1', ['offset' => 1]);
// Creates:
$routes['users/(:num)'] = 'users/show/$2';
Очередь обработки маршрутов
При работе с модулями проблема может возникнуть, если маршруты в приложении содержат подстановочные знаки. Тогда маршруты модуля не будут обработаны должным образом. Вы можете решить эту проблему, понизив приоритет обработки маршрутов с помощью параметра priority. Параметр принимает положительные целые числа и ноль. Чем больше указанное в «priority» число, тем ниже приоритет маршрута в очереди обработки:
// First you need to enable sorting.
$routes->setPrioritize();
// App\Config\Routes
$routes->add('(.*)', 'Posts::index', ['priority' => 1]);
// Modules\Acme\Config\Routes
$routes->add('admin', 'Admin::index');
// The "admin" route will now be processed before the wildcard router.
Чтобы отключить эту функциональность, вы должны вызвать метод с параметром false:
$routes->setPrioritize(false);
Примечание
По умолчанию все маршруты имеют приоритет 0. Отрицательные целые числа будут приводиться к абсолютному значению.
Параметры конфигурации маршрутов
Класс RoutesCollection предоставляет несколько параметров, которые влияют на все маршруты и могут быть изменены в соответствии с потребностями вашего приложения. Эти параметры доступны в верхней части app/Config/Routes.php.
Пространство имён по умолчанию
При сопоставлении контроллера с маршрутом маршрутизатор добавит значение по умолчанию для пространства имен перед контроллером, указанным в маршруте. По умолчанию это значение пустое, что заставляет каждый маршрут указывать полностью квалифицированный контроллер:
$routes->setDefaultNamespace('');
// Controller is \Users
$routes->add('users', 'Users::index');
// Controller is \Admin\Users
$routes->add('users', 'Admin\Users::index');
Если ваши контроллеры не явным образом имеют пространство имен, нет необходимости менять это. Если вы используете пространства имен для контроллеров, то можете изменить это значение, чтобы сэкономить на вводе:
$routes->setDefaultNamespace('App');
// Controller is \App\Users
$routes->add('users', 'Users::index');
// Controller is \App\Admin\Users
$routes->add('users', 'Admin\Users::index');
Контроллер по умолчанию
Когда пользователь посещает корень вашего сайта (например, example.com), контроллер для использования определяется значением, установленным методом setDefaultController(), если для него не существует явного маршрута. Значение по умолчанию — Home, что соответствует контроллеру в /app/Controllers/Home.php:
// example.com routes to app/Controllers/Welcome.php
$routes->setDefaultController('Welcome');
Контроллер по умолчанию также используется, когда не найдено соответствующего маршрута, и URI указывает на каталог в каталоге контроллеров. Например, если пользователь посещает example.com/admin, если был найден контроллер в /app/Controllers/admin/Home.php, он будет использован.
Метод по умолчанию
Это работает аналогично настройке контроллера по умолчанию, но используется для определения метода по умолчанию, который используется, когда найден контроллер, соответствующий URI, но сегмент для метода не существует. Значение по умолчанию — index.
В этом примере, если пользователь посетит example.com/products, и контроллер Products существует, будет выполнен метод Products::listAll():
$routes->setDefaultMethod('listAll');
Перевод дефисов URI
Этот параметр позволяет автоматически заменять дефисы (‘-‘) на подчёркивания в сегментах URI контроллера и метода, тем самым экономя дополнительные записи в маршруте, если вам нужно это сделать. Это необходимо, потому что дефис не является допустимым символом имени класса или метода и вызовет критическую ошибку, если вы попытаетесь его использовать:
$routes->setTranslateURIDashes(true);
Использовать только определённые маршруты
Когда не найден определённый маршрут, соответствующий URI, система попытается сопоставить этот URI с контроллерами и методами, как описано выше. Вы можете отключить это автоматическое сопоставление и ограничить маршруты только теми, которые определены вами, установив параметр setAutoRoute() в значение false:
$routes->setAutoRoute(false);
Предупреждение
Если вы используете защиту от CSRF, она не защищает запросы GET. Если URI доступен методом GET, защита от CSRF не будет работать.
Переопределение 404
Когда страница не найдена, соответствующая текущему URI, система отобразит общую страницу 404. Вы можете изменить это, указав действие с помощью параметра set404Override(). Значение может быть либо корректной парой класс/метод, как вы бы указали в любом маршруте, либо замыканием:
// Would execute the show404 method of the App\Errors class
$routes->set404Override('App\Errors::show404');
// Will display a custom view
$routes->set404Override(function ()
{
echo view('my_errors/not_found.html');
});
Обработка маршрутов по приоритету
Включает или отключает обработку очереди маршрутов по приоритету. Приоритет ниже определяется в опции маршрута. Отключено по умолчанию. Эта функция влияет на все маршруты. Пример использования понижения приоритета см. в Очереди обработки маршрутов:
// to enable $routes->setPrioritize(); // to disable $routes->setPrioritize(false);
© 2014–2020 British Columbia Institute of Technology
Licensed under the MIT License.
https://codeigniter.com/user_guide/incoming/routing.html