2008-09-24 4 views
15

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

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

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

ответ

12

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

Я делаю регистрацию на ключ и сопоставляю свою собственную контрольную строку. Возьмите приведенный ниже пример.Я посещаю /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", 
    )); 
} 

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

+0

Второй пример - это то, что я действительно думал о том, что я делаю ... (стиль RoR). Я просмотрю ваш код. – Mez 2008-09-25 07:08:06

1

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

Например

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

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

Это, AFAIK, как Django делает это

-4

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

Мне лично не нравится модель MVC, но большую часть времени реализуется как «View для веб-сайтов» компонента.

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

+0

Я использую MVC вещь. Я говорю о технической стороне или маршрутизации URL. Это не ответ на мой вопрос – Mez 2008-09-24 15:34:29

0

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

+0

Итак, очевидно, игнорируя ваши URL-адреса без ROA, это то же самое, что и мой ответ выше, но с использованием mod_rewrite с определенными правилами и «маршрутизации» через определенные парааметры, а не через код? – Mez 2008-09-24 15:40:18

-1

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

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

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

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

+0

действия не применяются к системе ROA, только для системы стиля RPC – Mez 2008-09-24 15:36:28

+0

Вы абсолютно правы ... Я неправильно понял вопрос. Это, и ROA бросил меня. Я всегда называл это REST. – 2008-09-24 20:16:08

+0

Это вообще не RESTFul. Только для записи. – DanMan 2012-06-25 09:57:59

2

Еще одна рама? - в любом случае ...

Уловка с маршрутизацией - передать ее всем контроллеру маршрутизации.

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

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

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

0

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

Например, в Slim Framework, пример двигателя маршрутизации может быть folllowing (на основе модели ${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/[email protected]', 
     'matches' => array('Application' => 'Members', 'Module' => 'Login'), 
    ), 
    'o' => array(// Output - how the router parse a query string into a route 
     '@Application=Members(&|&)Module=Login/[email protected]' => 'Members/Login/' 
    ) 
); 

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

$_FURLTEMPLATES['article'] = array(
    'i' => array(
     'pattern' => '@CMS/Articles/([\d]+)/[email protected]', 
     '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 - очень простой и красивый код.

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

Удачи вам! :)

0

Вы должны проверить 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);