Простой и когда-то элегантный роутинг фреймворка CodeIgniter полностью обновится в четвертой версии. Лонни Эцелл в очередной раз делится очень интересной информацией о новых возможностях. В этот раз речь пойдет о маршрутизации.
Основы маршрута
Чтобы освежить память вспомним, что в версии 3x маршрутизация была определена в простом массиве, где ключом был URl, а значением какой-либо элемент, куда необходимо было сделать направление.
Это был простой, элегантный и отлично работающий способ маршрутизации, что-то вроде этого:
$route['join'] = 'home/register';
$route['login'] = 'home/login';
$route['products/(:any)/details'] = 'products/show/$1';
Способности маршрутизации в других фреймворках превзошли эту простую элегантность. Даже в сообществе CodeIgniter, было несколько улучшенных маршрутизаторов способных послужить достойной альтернативой стандартному роутингу.
Итак, пришло время для обновления!
Первое, что необходимо было сделать — это возможность использования класса, вместо простого массива. Новые маршруты будут выглядеть следующим образом:
$routes->add('join', 'Home::register');
$routes->add('login', 'Home::login');
$routes->add('products/(:segment)', 'Products::show/$1');
Join маршрут направляется на главный контроллер, и его метод register(). Маршрут Products направляется на контроллер Products, с захваченным (:segment) передается на show () метод.
Модуль типа Функциональность
Почему новый формат? Потому что никто не хочет быть ограниченным /application/Controllers каталогом. Теперь появится возможность проложить маршрут к любому классу/методу.
Например, если у вас есть модуль Blog в пространстве имен App\Blog, то вы можете создать несколько маршрутов:
$routes->add('blog', 'App\Blog\Blog::index');
$routes->add('blog/category/(:segment)', 'App\Blog\Blog::byCategory/$1');
Если контроллер Blog живет в каталоге application/Controllers, отлично. Но если вы хотите переместить его в его собственную папку, скажем, application/Blog, вы можете обновить конфиг файл автозагрузки.
Замыкания
Маршруты больше не должны отображаться на контроллер. Если у вас есть простой процесс, вы можете указать путь к анонимной функции или замыканию, которое будет выполняться на месте любого контроллера.
$routes->add('pages/(:segment)', function($segment)
{
if (file_exists(APPPATH.'views/'.$segment.'.php'))
{
echo view($segment);
}
else
{
throw new CodeIgniter\PageNotFoundException($segment);
}
});
Заполнители
Все кто пользовался CodeIgniter привыкли к двум типам заполнителя:
:num будет соответствовать сегмент, содержащий только цифры.
:any будет соответствовать сегмент с любыми символами.
Теперь в CodeIgniter 4 будут внедрены следующие заполнители:
- (:any) будет соответствовать сегмент с любыми символами.
- (:segment) будет соответствовать сегмент с любыми символами за исключением прямой черты (слэша /).
- (:num) будет соответствовать сегмент, содержащий только цифры.
- (:alpha) будет соответствовать сегмент, содержащий любой символ
- (alphanum) будет соответствовать сегмент, содержащий комбинации из символов или чисел,
Также вы можете создать свой собственные правила маршрутизации, назначив регулярное выражение для него, поместив код в верхнюю часть файла маршрутизации.
$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');
HTTP Глаголы
Маршруты, добавленные таким образом будут доступны через HTTP-глаголы, чтобы проверить, является ли запрос GET, POST, PATCH, или даже из командной строки.
routes->get('products', 'Product::feature');
$routes->post('products', 'Product::feature');
$routes->put('products/(:num)', 'Product::feature');
$routes->delete('products/(:num)', 'Product::feature');
$routes->match(['get', 'post'], 'products/edit/(:num)', 'Product::edit/$1');
$routes->cli('maintenance/on', 'CLITools::maintenanceModeOn');
Создание стандартных ресурсов маршрутов
При работе с API лучше держать стандартный набор отображения маршрутов к тем же методам в каждом контроллере, просто чтобы сделать обслуживание проще. Вы можете легко сделать это с помощью метода ресурсов:
При работе с API-х лучше держать стандартный набор отображения маршрутов к тем же методам в каждом контроллере, просто чтобы сделать обслуживание проще. Вы можете легко сделать это с помощью метода ресурсов:
$routes->resources('photos');
Это создаст 5 стандартных маршрутов для ресурса:
HTTP Verb |
Path |
Action |
Used for... |
---|---|---|---|
GET |
/photos |
listAll |
display a list of photos |
GET |
/photos/{id} |
show |
display a specific photo |
POST |
/photos |
create |
create a new photo |
PUT |
/photos/{id} |
update |
update an existing photo |
DELETE |
/photos/{id} |
delete |
deletes an existing photo |
Нет больше магии
По умолчанию, URI, будет пытаться быть согласованным с контроллером / методом, если для него не существует маршрута. Это может быть легко обработано путем включения и выключения функции AutoRoute:
$routes->setAutoRoute(false);
Теперь, только маршруты, которые были определены, могут работать до приложения.
Группы
Маршруты могут быть сгруппированы вместе под общим префиксом. Это очень полезный функционал для организации маршрутизации.
$routes->group('admin', function($routes) {
$routes->add('users', 'Admin\Users::index');
$routes->add('blog', 'Admin\Blog::index');
});
Эти маршруты будут теперь все будут доступны под сегментом admin в URI, как:
example.com/admin/users
example.com/admin/blog
Окружения групп
Другая форма группировки, environment() — позволяет ограничить некоторые маршруты для работы только в конкретной среде.
$routes->environment('development', function($routes)
{
$routes->add('builder', 'Tools\Builder::index');
});
Перенаправление Старые маршруты
Если ваш сайт имеет несколько страниц, которые были перемещены, вы можете назначить перенаправление маршрутов, которые будут получать 302 (временный) статус и отправлять пользователя на нужную страницу.
$routes->addRedirect('users/about', 'users/profile');
Это позволит перенаправить любые маршруты, соответствующие users/about на новое место users/profile.
Использование маршрутов в представлениях
Одной из наиболее слабой вещью при создании ссылок внутри отображения, является изменение их адреса. Теперь CodeIgniter 4 предоставляет несколько различных инструментов, чтобы помочь обойти эту проблему.
Именованные маршруты
В любое время вы создать маршрут и можете назначить пользовательское имя на маршрут. Для возврата правильного относительного URL необходимо применять функцию route_to ():
// Create the route
$route->add('auth/login', 'Users::login', ['as' => 'login']);
// Use it in a view
<a href="<?= route_to('login') ?>">Login</a>
Именованные маршруты, используемые таким образом, могут также принимать параметры:
// The route is defined as:
$routes->add('users/(:id)/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>
Обратная маршрутизация
Для еще более точного управления, вы можете использовать функцию route_to (), чтобы найти маршрут, который соответствует контроллеру / методу и параметрам.
// The route is defined as:
$routes->add('users/(:id)/gallery(:any)', '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('Galleries::showUserGallery', 15, 12) ?>">View Gallery</a>
Глобальные параметры
Любой из методов создания маршрута можно передать массив опций, которые могут помочь дополнительно уточнить маршрут, делая такие вещи, как:
- назначить пространство имен для контроллеров
- ограничить маршрут к определенному имени хоста, или суб-домену
- сместить совпавшие параметры, чтобы игнорировать один или несколько (которые могли быть использованы для языка, версии, и т.д.)
Нужно больше? Настройте сами!
Если вы обнаружите, что вам нужно что-то отличное от стандартного маршрутизатора, то вы можете заменить класс RouteCollection вашим собственным и использовать свое решение. Класс RouteCollection отвечает только для чтения и разбора маршрутов, а не для выполнения фактической маршрутизации, так что все будет работать с вашим решением.
Более подробная информации появится с выходом официальной документации.
Ссылки по теме
Блог Лонни Эцелла: Routes in CodeIgniter 4
CodeIgniter Wikipedia: ru.wikipedia.org/wiki/CodeIgniter
Официальный сайт CodeIgniter: www.codeigniter.com
Официальный форум CodeIgniter: forum.codeigniter.com
CodeIgniter 4: https://habrahabr.ru/post/275657/
CI Community Apps: https://habrahabr.ru/post/276375/
Requests и Responses в CodeIgniter 4: https://habrahabr.ru/post/278489/
Внедрение зависимостей в CodeIgniter 4: https://habrahabr.ru/post/278641/
evnuh
Перенимая более мощные, но сложные решения из других фреймворков, CodeIgniter становится ничем от них неотличим. И зачем он тогда нужен, такой же, как и все, только на 5 лет опоздавший?
condor-bird
То же самое можно сказать абсолютно про любой фреймворк. Зачем Yii, если есть Symfony? Зачем Laravel, если есть Yii? Здесь также можно говорить о всеми излюбленном выражении "строить велосипед", которое в последнее время я вижу очень часто и не по месту. И т.д. и т.п.
Таким же как другие он не будет по той причине, что текущие владельцы фреймворка не желают отходить от изначально заложенной идеологии CodeIgniter. Он по прежнему ожидается быть простым и быстрым фреймворком, но с абсолютно новым функционалом.
Здесь нет необходимости сравнивать с другими фреймворками, с которыми по сути сравнивать и не нужно. Сравнивать несравниваемое можно много и долго. Это не правильно. Но, тем не менее, мы все постоянно видим и слышим эти сравнения. Да, CodeIgniter не планирует быть RAD, в нем не будет ничего лишнего, кроме того функционала, который действительно необходим в большинстве случаев. Остальное, думаю, должны будут решать как раз аддоны приложений (демо блогов, админки, crud, авторизация).
Согласитесь, что на самом деле достатоно крупных и хороших игроков, среди фреймворков php, можно перечислить по пальцам. Почему бы здесь не быть еще одному? Тем более такому старому. Да и не вижу ничего плохого в появлении новых фреймворков.
evnuh
Это решение плохое не потому, что он будет похож на остальных, а потому, что мы потеряем единственный максимально быстрый, простой и понятный с первого взгляда каждому школьнику фреймворк.
Вот касаемо этого решения с маршрутизацией. Чем не устроило людей жёсткое правило связи url -> метод контроллера? Ваш аргумент (или не ваш, т.к. вы не пометили статью переводом и я не могу найти ссылку на оригинал статьи, хоят уверен, что это перевод):
Не содержит никакой конкретики, чем превзошли, что значит "улучшенный", "достойный", "ламповый" и т.д.?
condor-bird
Почему же потеряли? Он таким и останется: быстрым и простым. Ничего лишнего не прибавится.
(Все необходимые ссылки, в том числе первоисточник, я всегда оставляю в самом низу "Ссылки по теме". Трудно их не заметить. Интересующая вас ссылка идет сразу же первой. Мои заметки и статьи я бы не назвал целиком переводом, потому как где-то в одном месте я использую точный перевод, где-то просто пересказываю написанное своими словами, где-то могу дополнить. Поэтому не стал ставить метку "Перевод").
Какую именно конкретику вы хотели увидеть?
А то и значит, что роутинг в других фреймворках (например: Yii, Laravel) намного гибче, с которым приятно работать. Возможностей там по функционалу больше. Поэтому все и начали лепить свои роутинги, чтобы компенсировать недостающие потребности. Для написания простого и несложного приложения роутинг CodeIgniter сойдет. Но когда речь идет о нестандартном приложении то он никуда не годится.
Fesor
А нужен ли он, быстрый и простой? Сейчас "быстрый и простой" фреймворк можно на пакетах композера собрать за пару часов. И будет удобно, и быстро, и ничего лишнего, с теми же проблемами реюза готовых решений, а может даже проблем будет меньше.
evnuh
Нука, пример задачи, которая не решалась на старом роутинге, или решалась очень сложно и громоздко, а теперь стала легче?