Маршрутизации в CodeIgniter 4

Простой и когда-то элегантный роутинг фреймворка 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/

Комментарии (6)


  1. evnuh
    10.03.2016 01:53
    +7

    Перенимая более мощные, но сложные решения из других фреймворков, CodeIgniter становится ничем от них неотличим. И зачем он тогда нужен, такой же, как и все, только на 5 лет опоздавший?


    1. condor-bird
      10.03.2016 10:15
      +3

      То же самое можно сказать абсолютно про любой фреймворк. Зачем Yii, если есть Symfony? Зачем Laravel, если есть Yii? Здесь также можно говорить о всеми излюбленном выражении "строить велосипед", которое в последнее время я вижу очень часто и не по месту. И т.д. и т.п.
      Таким же как другие он не будет по той причине, что текущие владельцы фреймворка не желают отходить от изначально заложенной идеологии CodeIgniter. Он по прежнему ожидается быть простым и быстрым фреймворком, но с абсолютно новым функционалом.
      Здесь нет необходимости сравнивать с другими фреймворками, с которыми по сути сравнивать и не нужно. Сравнивать несравниваемое можно много и долго. Это не правильно. Но, тем не менее, мы все постоянно видим и слышим эти сравнения. Да, CodeIgniter не планирует быть RAD, в нем не будет ничего лишнего, кроме того функционала, который действительно необходим в большинстве случаев. Остальное, думаю, должны будут решать как раз аддоны приложений (демо блогов, админки, crud, авторизация).

      Согласитесь, что на самом деле достатоно крупных и хороших игроков, среди фреймворков php, можно перечислить по пальцам. Почему бы здесь не быть еще одному? Тем более такому старому. Да и не вижу ничего плохого в появлении новых фреймворков.


      1. evnuh
        10.03.2016 14:40

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

        Вот касаемо этого решения с маршрутизацией. Чем не устроило людей жёсткое правило связи url -> метод контроллера? Ваш аргумент (или не ваш, т.к. вы не пометили статью переводом и я не могу найти ссылку на оригинал статьи, хоят уверен, что это перевод):

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

        Не содержит никакой конкретики, чем превзошли, что значит "улучшенный", "достойный", "ламповый" и т.д.?


        1. condor-bird
          10.03.2016 15:13

          Почему же потеряли? Он таким и останется: быстрым и простым. Ничего лишнего не прибавится.

          (Все необходимые ссылки, в том числе первоисточник, я всегда оставляю в самом низу "Ссылки по теме". Трудно их не заметить. Интересующая вас ссылка идет сразу же первой. Мои заметки и статьи я бы не назвал целиком переводом, потому как где-то в одном месте я использую точный перевод, где-то просто пересказываю написанное своими словами, где-то могу дополнить. Поэтому не стал ставить метку "Перевод").

          Какую именно конкретику вы хотели увидеть?
          А то и значит, что роутинг в других фреймворках (например: Yii, Laravel) намного гибче, с которым приятно работать. Возможностей там по функционалу больше. Поэтому все и начали лепить свои роутинги, чтобы компенсировать недостающие потребности. Для написания простого и несложного приложения роутинг CodeIgniter сойдет. Но когда речь идет о нестандартном приложении то он никуда не годится.


          1. Fesor
            10.03.2016 23:38

            А нужен ли он, быстрый и простой? Сейчас "быстрый и простой" фреймворк можно на пакетах композера собрать за пару часов. И будет удобно, и быстро, и ничего лишнего, с теми же проблемами реюза готовых решений, а может даже проблем будет меньше.


          1. evnuh
            11.03.2016 18:12

            Нука, пример задачи, которая не решалась на старом роутинге, или решалась очень сложно и громоздко, а теперь стала легче?