因此,我正在編寫一個框架,我要基於我正在開發的幾個應用程序(該框架在那裏,因此我有一個可以使用的環境,以及一個可讓我,例如,使用單一登錄)PHP應用程序URL路由
我想製作這個框架,它的應用程序使用面向資源的架構。
現在,我想創建一個可由APP編寫器擴展的URL路由類(也可能由CMS應用程序用戶進行擴展,但未來將提前推出),並試圖找出最佳做法它通過查看其他應用程序如何執行它。
因此,我正在編寫一個框架,我要基於我正在開發的幾個應用程序(該框架在那裏,因此我有一個可以使用的環境,以及一個可讓我,例如,使用單一登錄)PHP應用程序URL路由
我想製作這個框架,它的應用程序使用面向資源的架構。
現在,我想創建一個可由APP編寫器擴展的URL路由類(也可能由CMS應用程序用戶進行擴展,但未來將提前推出),並試圖找出最佳做法它通過查看其他應用程序如何執行它。
我更喜歡使用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",
));
}
此外,您可以在右側爲您的路由字符串定義任何默認值。只是不要忘記記錄它們,否則你會迷惑人。如果您沒有在右側包含函數名,我現在正在調用索引。 Here是我當前的代碼。您可能需要將其更改爲處理錯誤的方式和/或默認操作。
使用Regexs列表匹配,我應該使用
例如
^/users/[\w-]+/bookmarks/(.+)/$
^/users/[\w-]+/bookmarks/$
^/users/[\w-]+/$
哪個對象優點:尼斯和簡單,讓我直接定義路線 缺點:必須是有序的,不使其易於在(非常容易出錯)添加新的東西
這一點,據我所知,Django是如何做它
我想了很多框架使用Apache的mod_rewrite和前端控制器的組合。使用mod_rewrite,您可以將如下所示的URL變爲:/ people/get/3: index.php?controller = people & method = get & id = 3。 Index.php將實現您的前端控制器,它根據給定的參數來路由頁面請求。
因此,顯然忽略你的非ROA網址,它與我上面的答案一樣,但使用mod_rewrite與特定的規則,並通過特定的paraameters,而不是通過代碼「路由」? – Mez 2008-09-24 15:40:18
默認Zend的MVC框架使用像
/router/controller/action/key1/value1/key2/value2
其中router
是路由器文件(通過mod_rewrite
映射的結構,controller
是從由從Zend_Controller_Action
和action
派生的類中定義的控制器的動作的處理程序引用了控制器中的一個方法,名爲actionAction
。鍵/值對可以按任何順序排列,並可作爲關聯數組的行爲方法使用。 t在我自己的代碼中,到目前爲止它的工作還算不錯。
又一個框架? - 無論如何...
路由的訣竅是把它傳遞給你的路由控制器。
你可能想使用類似的東西,我在這裏記載:
http://www.hm2k.com/posts/friendly-urls
第二個解決方案,您可以使用類似Zend框架的URL。
正如您所料,有很多方法可以做到這一點。
例如,在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
)獲取每個請求方法的方法(例如獲取,發佈,放置,刪除等),並獲取一個路由作爲第一個參數,並將回調作爲第二個參數。
路由可以獲取令牌 - 這是「變量」,它將在運行時基於某些數據(例如成員名稱,文章ID,組織位置名稱或其他 - 就像在每個路由控制器中一樣)發生更改。
就我個人而言,我喜歡這種方式,但我認爲它對於高級框架來說不夠靈活。
由於我與ZF和目前的Yii工作,我有我作爲一個企業的框架的一部分,創造了一個路由器,我工作的一個例子:
路由引擎是基於在正則表達式(類似於@ gradbot的一個),但得到了雙向對話,所以如果你的客戶端不能運行mod_rewrite(在Apache中)或在他或她的服務器上添加重寫規則,他或她仍然可以使用傳統包含查詢字符串的網址。
該文件包含一個陣列,每個的話,每個項目類似於該實施例中:
$_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'
)
);
底線,正如我認爲的那樣,可能性是無止境的,它只取決於你希望你的框架有多複雜,以及你希望如何使用它。
如果是,例如,只是打算成爲一個Web服務或簡單的網站包裝 - 只需與Slim框架的寫作風格 - 非常簡單和漂亮的代碼。
但是,如果你想開發複雜的網站使用它,我認爲正則表達式是解決方案。
祝你好運! :)
你應該看看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);
第二個例子非常符合Ive實際上正在考慮的事情......(RoR風格) - 我將通過你的代碼來看看。 – Mez 2008-09-25 07:08:06