2015-07-12 50 views
2

我創建代表的URI的模板,我後面想用不同的ID使用字符串數組字符串模板,我用「%ID」作爲佔位符PHP創建注入字符串後

$template = array() 
$template[] = "/campaigns/%id/"; 
$template[] = "/campaigns/%id/pictures"; 
$template[] = "/campaigns/%id/likes"; 

現在我還設置可選的ID的排列:

$ids = array("123","456","789"); 

我有檢查是否一個給定的URI是無效的功能。 該函數將收到一個URI,然後將其與所有按照有效的URI的模板和IDS我定義:

public function isUriAllowed($uri){ 
    $allowedUris = $this->getTemplateUris(); 
    foreach($this->ids as $id) 
    { 
     foreach($allowedUris as $allowedUri) 
     { 
      $allowedUri = str_replace($this->idPlaceHolder,$id,$allowedUri); 
      if (strcmp($allowedUri,$uri) == 0) 
       return true; 
     } 
    } 
    return false; 
} 

我有一種感覺:還有一個更優雅的方式來實現我試圖去做,但我不知道該怎麼做。

任何想法?

+0

除了建立一個大的正則表達式來匹配,我看不到一個更好的方法來做到這一點。這也許是性能最好的解決方案。然而,對於大多數路由實現,我會說,你不會想要一些大的'isvalid'類型的函數,它既驗證路由是否格式良好,又匹配存在的路由。更好地構建路由到一個特定的id(例如在MVC中會傳遞給一個控制器),然後讓這個檢查單獨失敗,如果URL匹配一個路由,但在該路由沒有可用的ID。 –

+0

它實際上不會做路線。它檢查特定用途是否被授權到特定路線。試圖爲端點構建範圍。 –

+0

這個函數會在同一個請求中被多次調用嗎? –

回答

0

您可以使用此代碼查詢的網址:

$test_url = '/campaigns/123/pictures'; 
$ids_availables = array("123","456","789"); 

$valid = preg_match('/\/campaigns\/('.implode('|', $ids_availables).')\/(pictures|likes)?/', $test_url, $matches); 
/* print (boolean) if $test_url is valid */ 
var_dump($valid); 
/* if is a valid url, $matches is an array that contains campaing_id and pictures/likes values */ 
var_dump($matches); 

編輯:對不起,我編輯在sintaxis正確的錯誤。

0

讓我猜,你正在試圖創建一種路由器??,讓我分享你我很久以前做的路由器。

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,或僅僅指剛做需要每個控制器你將會使用。

如果不是這樣的話,我的道歉。畢竟,你的代碼也有你的答案。好好享受!!

+0

我讀過你並沒有試圖做一個路由器,但是你想要檢查這個url是否對某個特定的用途有效,以及你之前定義的參數。我的路由器可以實現你想要的,只需傳遞給set_route第三個參數來定義你在哪個佔位符中允許的參數,然後在最後四行代碼中調用一個控制器繼續流動。 –