2015-07-12 51 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第三个参数来定义你在哪个占位符中允许的参数,然后在最后四行代码中调用一个控制器继续流动。 –