讓我猜,你正在試圖創建一種路由器??,讓我分享你我很久以前做的路由器。
class Router {
private $request_uri;
private $routes;
private static $instance = false;
const DEFAULT_CONTROLLER = "MyController";
const DEFAULT_ACTION = "myAction";
public static function get_instance() {
if(!self::$instance) {
$class = get_called_class();
self::$instance = new $class();
}
return self::$instance;
}
protected function __construct() {
list($this->request_uri) = explode('?', $_SERVER['REQUEST_URI']);
}
public function set_route($route, $target = [], $condition = []) {
$url_regex = preg_replace_callback('@:[\w][email protected]', function($matches) use ($condition) {
$res = '([a-zA-Z0-9_\+\-%]+)';
$key = str_replace(':', '', $matches[0]);
if(array_key_exists($key, $condition)) $res = '('.$condition[$key].')';
return $res;
}, $route);
preg_match_all('@:([\w]+)@', $route, $keys, PREG_PATTERN_ORDER);
$this->routes[$route] = ['regex' => $url_regex .'/?', 'target' => $target, 'keys' => $keys[0]];
}
public function run() {
$params = [];
foreach($this->routes as $v) {
if(preg_match('@^'.$v['regex'].'[email protected]', $this->request_uri, $values)) {
if(isset($v['target']['controller'])) $controller = $v['target']['controller'];
if(isset($v['target']['action'])) $action = $v['target']['action'];
for($i = count($values) -1; $i--;) {
$params[substr($v['keys'][$i], 1)] = $values[$i +1];
}
break;
}
}
$controller = isset($controller) ? $controller : self::DEFAULT_CONTROLLER;
$action = isset($action) ? $action : self::DEFAULT_ACTION;
$redirect = new $controller();
$redirect->{$action}(array_merge($params, $_GET, $_POST, $_COOKIE));
}
}
如何使用它:
require_once 'Router.php';
$router = Router::get_instance();
$router->set_route("/");
$router->set_route("/nocontroller/noaction", ['controller' => 'NoController']);
$router->set_route("/nocontroller/nocontroller", ['action' => 'without']);
$router->set_route("/another/echoes/:param", ['controller' => 'Another', 'action' => 'echoes'], ['param' => '[a-z]{3}']);
$router->set_route("/another/echoes/:param/:id", ['controller' => 'Another', 'action' => 'dump'], ['param' => '[a-z]{3}', 'id' => '[\d]{1,8}']);
$router->set_route("/another/echoes/:param/some/:id", ['controller' => 'Another', 'action' => 'dump'], ['param' => '[a-z]{3}', 'id' => '[\d]{1,8}']);
$router->set_route("/another/echoes/:param/some/:id/:more", ['controller' => 'Another', 'action' => 'dump'], ['param' => '[a-z]{3}', 'id' => '[\d]{1,8}']);
$router->run();
好吧,你需要使用自動加載磁帶機...如果你想它一個自討苦吃:P,或僅僅指剛做需要每個控制器你將會使用。
如果不是這樣的話,我的道歉。畢竟,你的代碼也有你的答案。好好享受!!
除了建立一個大的正則表達式來匹配,我看不到一個更好的方法來做到這一點。這也許是性能最好的解決方案。然而,對於大多數路由實現,我會說,你不會想要一些大的'isvalid'類型的函數,它既驗證路由是否格式良好,又匹配存在的路由。更好地構建路由到一個特定的id(例如在MVC中會傳遞給一個控制器),然後讓這個檢查單獨失敗,如果URL匹配一個路由,但在該路由沒有可用的ID。 –
它實際上不會做路線。它檢查特定用途是否被授權到特定路線。試圖爲端點構建範圍。 –
這個函數會在同一個請求中被多次調用嗎? –