Маршрутизация URL-адресов PHP-приложений

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

Я хочу сделать эту структуру, и приложения, в которых она использует ресурсо-ориентированную архитектуру.

Теперь я хочу создать класс маршрутизации URL-адресов, который может быть расшифрован авторами APP (и, возможно, также пользователями CMS App, но это будет WAYYYY впереди в будущем), и я пытаюсь найти лучший способ сделать это, посмотрев на как это делают другие приложения.

Related of "Маршрутизация URL-адресов PHP-приложений"

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

Я делаю reg ex на ключе и сопоставляю свою собственную строку управления. Возьмите приведенный ниже пример. Я посещаю /api/related/joe и мой класс маршрутизатора создает новый объект ApiController и вызывает его метод relatedDocuments(array('tags' => 'joe'));

 // the 12 strips the subdirectory my app is running in $index = urldecode(substr($_SERVER["REQUEST_URI"], 12)); Route::process($index, array( "#^api/related/(.*)$#Di" => "ApiController/relatedDocuments/tags", "#^thread/(.*)/post$#Di" => "ThreadController/post/title", "#^thread/(.*)/reply$#Di" => "ThreadController/reply/title", "#^thread/(.*)$#Di" => "ThreadController/thread/title", "#^ajax/tag/(.*)/(.*)$#Di" => "TagController/add/id/tags", "#^ajax/reply/(.*)/post$#Di"=> "ThreadController/ajaxPost/id", "#^ajax/reply/(.*)$#Di" => "ArticleController/newReply/id", "#^ajax/toggle/(.*)$#Di" => "ApiController/toggle/toggle", "#^$#Di" => "HomeController", )); 

Чтобы сохранить ошибки и простоту, вы можете разделить таблицу. Таким образом вы можете поместить таблицу маршрутизации в класс, который он контролирует. Взяв приведенный выше пример, вы можете объединить три потока вызовов в один.

 Route::process($index, array( "#^api/related/(.*)$#Di" => "ApiController/relatedDocuments/tags", "#^thread/(.*)$#Di" => "ThreadController/route/uri", "#^ajax/tag/(.*)/(.*)$#Di" => "TagController/add/id/tags", "#^ajax/reply/(.*)/post$#Di"=> "ThreadController/ajaxPost/id", "#^ajax/reply/(.*)$#Di" => "ArticleController/newReply/id", "#^ajax/toggle/(.*)$#Di" => "ApiController/toggle/toggle", "#^$#Di" => "HomeController", )); 

Затем вы определяете ThreadController :: route таким образом.

 function route($args) { Route::process($args['uri'], array( "#^(.*)/post$#Di" => "ThreadController/post/title", "#^(.*)/reply$#Di" => "ThreadController/reply/title", "#^(.*)$#Di" => "ThreadController/thread/title", )); } 

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

Еще одна структура? — так или иначе…

Трюк с маршрутизацией – передать все это вашему контроллеру маршрутизации.

Вероятно, вы захотите использовать что-то похожее на то, что я документировал здесь:

http://www.hm2k.com/posts/friendly-urls

Второе решение позволяет использовать URL-адреса, похожие на Zend Framework.

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

Например

 ^/users/[\w-]+/bookmarks/(.+)/$ ^/users/[\w-]+/bookmarks/$ ^/users/[\w-]+/$ 

Плюсы: Ницца и просто, позволяет мне определять маршруты напрямую. Минусы: нужно было бы заказать, а не упрощать добавление новых вещей (очень склонный к ошибкам)

Это, афайк, как это делает Django

Я думаю, что многие фреймворки используют комбинацию mod_rewrite от Apache и фронтальный контроллер. С mod_rewrite вы можете повернуть URL-адрес следующим образом: / people / get / 3 в это: index.php? Controller = people & method = get & id = 3. Index.php реализует ваш фронт-контроллер, который направляет запрос страницы на основании заданных параметров.

Как и следовало ожидать, есть много способов сделать это.

Например, в Slim Framework пример механизма маршрутизации может быть следующим (на основе шаблона ${OBJECT}->${REQUEST METHOD}(${PATTERM}, ${CALLBACK}) ):

 $app->get("/Home", function() { print('Welcome to the home page'); } $app->get('/Profile/:memberName', function($memberName) { print( 'I\'m viewing ' . $memberName . '\'s profile.' ); } $app->post('/ContactUs', function() { print( 'This action will be fired only if a POST request will occure'); } 

Таким образом, инициализированный экземпляр ( $app ) получает метод для метода запроса (например, get, post, put, delete и т. Д.) И получает маршрут в качестве первого параметра и обратного вызова как второго.

Маршрут может получать токены – которые являются «переменными», которые будут меняться во время выполнения на основе некоторых данных (таких как имя участника, идентификатор статьи, название местоположения организации или что-то еще – вы знаете, как и в каждом контроллере маршрутизации).

Лично мне это нравится, но я не думаю, что он будет достаточно гибким для передовой структуры.

Поскольку я работаю в настоящее время с ZF и Yii, у меня есть пример маршрутизатора, который я создал как часть структуры для компании, в которой я работаю:

Механизм маршрутизации основан на регулярном выражении (аналогично одному из них – @ gradbot), но получил двухсторонний разговор, поэтому, если ваш клиент не может запустить mod_rewrite (в Apache) или добавить правила перезаписи на своем сервере, он или она все еще могут использовать традиционные URL-адреса с строкой запроса.

Файл содержит массив, каждый из которых, каждый элемент аналогичен этому примеру:

 $_FURLTEMPLATES['login'] = array( 'i' => array( // Input - how the router parse an incomming path into query string params 'pattern' => '@Members/Login/?@i', 'matches' => array( 'Application' => 'Members', 'Module' => 'Login' ), ), 'o' => array( // Output - how the router parse a query string into a route '@Application=Members(&|&)Module=Login/?@' => 'Members/Login/' ) ); 

Вы также можете использовать более сложные комбинации, такие как:

 $_FURLTEMPLATES['article'] = array( 'i' => array( 'pattern' => '@CMS/Articles/([\d]+)/?@i', 'matches' => array( 'Application' => "CMS", 'Module' => 'Articles', 'Sector' => 'showArticle', 'ArticleID' => '$1' ), ), 'o' => array( '@Application=CMS(&|&)Module=Articles(&|&)Sector=showArticle(&|&)ArticleID=([\d]+)@' => 'CMS/Articles/$4' ) ); 

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

Если это, например, просто предназначено для веб-службы или простой веб-обложки, просто используйте стиль написания Slim framework – очень простой и красивый код.

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

Удачи! 🙂

Вы должны проверить Pux https://github.com/c9s/Pux

Вот краткий обзор

 <?php require 'vendor/autoload.php'; // use PCRE patterns you need Pux\PatternCompiler class. use Pux\Executor; class ProductController { public function listAction() { return 'product list'; } public function itemAction($id) { return "product $id"; } } $mux = new Pux\Mux; $mux->any('/product', ['ProductController','listAction']); $mux->get('/product/:id', ['ProductController','itemAction'] , [ 'require' => [ 'id' => '\d+', ], 'default' => [ 'id' => '1', ] ]); $mux->post('/product/:id', ['ProductController','updateAction'] , [ 'require' => [ 'id' => '\d+', ], 'default' => [ 'id' => '1', ] ]); $mux->delete('/product/:id', ['ProductController','deleteAction'] , [ 'require' => [ 'id' => '\d+', ], 'default' => [ 'id' => '1', ] ]); $route = $mux->dispatch('/product/1'); Executor::execute($route); 

По умолчанию среда MVC Zend использует структуру, подобную

 /router/controller/action/key1/value1/key2/value2 

где router является файлом маршрутизатора (отображается через mod_rewrite , controller – из обработчика действия контроллера, который определяется классом, который происходит из Zend_Controller_Action и action ссылается на метод в контроллере с именем actionAction . actionAction ключ / значение могут идти в любом порядке и доступны для метода действия как ассоциативный массив.

В прошлом я использовал что-то подобное в своем собственном коде, и до сих пор он работал достаточно хорошо.

Попробуйте взглянуть на шаблон MVC .
Zend Framework использует его, например, но также CakePHP, CodeIgniter, …

Мне лично не нравится модель MVC, но это большая часть времени реализована как компонент «Просмотр для Интернета».

Решение в значительной степени зависит от предпочтения …