Поэтому я пишу фреймворк, на котором я хочу основать несколько приложений, над которыми я работаю (инфраструктура там, поэтому у меня есть среда для работы, и система, которая позволит мне, например, использовать один Подпишись)
Я хочу сделать эту структуру, и приложения, в которых она использует ресурсо-ориентированную архитектуру.
Теперь я хочу создать класс маршрутизации URL-адресов, который может быть расшифрован авторами APP (и, возможно, также пользователями CMS App, но это будет WAYYYY впереди в будущем), и я пытаюсь найти лучший способ сделать это, посмотрев на как это делают другие приложения.
Я предпочитаю использовать 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, но это большая часть времени реализована как компонент «Просмотр для Интернета».
Решение в значительной степени зависит от предпочтения …