2013-06-28 24 views
3

我在一個路由器在PHP中匹配一個模式,如「users /:id」,路由,如「users/123」 ,返回類似「id」=> 123的東西。這是我迄今爲止所擁有的。使用正則表達式來匹配一個模式的URL,返回一個鍵陣列

function match_path($path, $pattern){ 
if ($path == $pattern){ 
    return true; 
} 
// check for :replacements 
if (strpos($pattern, ":")!== false) { 
    // split path & pattern into fragments 
    $split_path = explode('/',$path); 
    $split_pattern = explode('/', $pattern); 
    // check that they are the same length 
    if (count($split_path) !== count($split_pattern)){ 
    return false; 
    } 
    // iterate over pattern 
    foreach ($split_pattern as $index => $fragment) { 
    // if fragment is wild 
    if (strpos($fragment, ":") == 0){ 
     $params[substr($fragment, 1)] = $split_path[$index]; 
    // if fragment doesn't match 
    } elseif ($fragment !== $split_path[$index]) { 
     return false; 
    } 
    // continue if pattern matches 
    } 
    // returns hash of extracted parameters 
    return $params; 
} 
return false; 

} 

我敢肯定,必須有一種方法,用正則表達式乾淨地做到這一點。

更好的是,很可能有一個PHP函數可以做到這一點。

+0

我不能確定你打算用它做,但'.htaccess'甚至是可能的,這是通常用於看中的URL – Sumurai8

+0

好像他是試圖在應用程序級別實現路由。 '.htaccess'從開發的角度來看速度更快但不夠靈活。 – acobster

回答

1

PHP on Rails,呃? ;-)

關於strpos行爲的重要提示:你應該檢查使用嚴格===運營商,因爲它可能會返回錯誤(來源:http://php.net/manual/en/function.strpos.php )。一個粗略的讀/測試之後,這是我所看到的錯誤與腳本...

<?php 
// routes-test.php 

echo "should be [ id => 123 ]:\n"; 
var_dump(match_path('user/123', 'user/:id')); 

function match_path($path, $pattern) { ... } 
?> 

// cmd line 
$ php routes-test.php # your implementation 
should be [ id => 123 ]: 
array(2) { 
    ["ser"]=> 
    string(4) "user" 
    ["id"]=> 
    string(3) "123" 
} 
$ php routes-test.php # using === 
should be [ id => 123 ]: 
array(1) { 
    ["id"]=> 
    string(3) "123" 
} 

你應該採取YAGNI的方法來使用正則表達式。如果你所做的只是匹配諸如/^:\w+$/之類的東西,那麼你可以更快地做到這一點,並且可以與strpos和朋友進行比較。

0

如何使用這樣的東西?

/** 
* Compares a url to a pattern, and populates any embedded variables 
* Returns false if the pattern does not match 
* Returns an array containing the placeholder values if the pattern matches 
* If the pattern matches but does not contain placeholders, returns an empty array 
*/ 
function checkUrlAgainstPattern($url, $pattern) { 
    // parse $pattern into a regex, and build a list of variable names 
    $vars = array(); 
    $regex = preg_replace_callback(
     '#/:([a-z]+)(?=/|$)#', 
     function($x) use (&$vars) { 
      $vars[] = $x[1]; 
      return '/([^/]+)'; 
     }, 
     $pattern 
    ); 

    // check $url against the regex, and populate variables if it matches 
    $vals = array(); 
    if (preg_match("#^{$regex}$#", $url, $x)) { 
     foreach ($vars as $id => $var) { 
      $vals[$var] = $x[$id + 1]; 
     } 
     return $vals; 
    } else { 
     return false; 
    } 
} 

這使用preg_replace_callback()到兩個模式轉換爲正則表達式,並捕獲佔位符的列表,然後preg_match(),以評估對造成正則表達式的URL,然後拉出佔位符值。

使用的一些例子:

checkUrlAgainstPattern('/users/123', '/users/:id'); 
// returns array('id' => '123') 

checkUrlAgainstPattern('/users/123/123', '/users/:id'); 
// returns false 

checkUrlAgainstPattern('/users/123/details', '/users/:id/:page'); 
// returns array('id' => '123', 'page' => 'details') 
相關問題