2011-12-06 11 views
3

私は自分の軽量MVCフレームワークをPHPのために働いています。私はある時点でオープンソースライセンスの下でリリースするかもしれません。ここで私のPHP MVCフレームワークでのルーティング

は私がルートを処理するために使用されているものです:

function routes($routes, $uriPath) { 

    // Loop through every route and compare it with the URI 
    foreach ($routes as $route => $actualPage) { 

     // Create a route with all identifiers replaced with ([^/]+) regex syntax 
     // E.g. $route_regex = shop-please/([^/]+)/moo (originally shop-please/:some_identifier/moo) 
     $route_regex = preg_replace('@:[^/][email protected]', '([^/]+)', $route); 

     // Check if URI path matches regex pattern, if so create an array of values from the URI 
     if(!preg_match('@' . $route_regex . '@', $uriPath, $matches)) continue; 

     // Create an array of identifiers from the route 
     preg_match('@' . $route_regex . '@', $route, $identifiers); 

     // Combine the identifiers with the values 
     $this->request->__get = array_combine($identifiers, $matches); 
     array_shift($this->request->__get); 

     return $actualPage; 
    } 

    // We didn't find a route match 
    return false; 
} 

$ルートは、このような形式に渡された配列である:

$routes = array(
    // route => actual page 
    'page/:action/:id' => 'actualPage', 
    'page/:action' => 'actualPage', 
) 

$ uriPathは大手将来をせずにURIパスですスラッシュ私のページコントローラでページ/更新/ 102

私はそうのようなルート情報にアクセスすることができます

echo $this->request->__get['action']; 
// update 

echo $this->request->__get['id']; 
// 102 

私の質問は基本的に「これを簡略化または最適化することができますか?」されています。正規表現とpreg_replaceとpreg_match呼び出しの数を単純化することに特に重点を置いています。

+0

あなたはパフォーマンスの問題を持っていますか?ここを見てくださいhttp://kohanaframework.org/3.2/guide/api/Route –

答えて

5

このようなシナリオで正規表現を使用するのは、非常に賢明ではありません。なぜなら、正規表現を使用しないで行うことができるからです。私は正規表現なしでまったく同じことをする以下の単純なコードを書いています。

コード:

<?php 
$routes    = array 
(
    // actual path => filter 
    'foo' => array('page', ':action', ':id'), 
    'bar' => array('page', ':action') 
); 

/** 
* @author Gajus Kuizinas <[email protected]> 
* @copyright Anuary Ltd, http://anuary.com 
* @version 1.0.0 (2011 12 06) 
*/ 
function ay_dispatcher($url, $routes) 
{ 
    $final_path   = FALSE; 

    $url_path   = explode('/', $url); 
    $url_path_length = count($url_path); 

    foreach($routes as $original_path => $filter) 
    { 
     // reset the parameters every time in case there is partial match 
     $parameters  = array(); 

     // this filter is irrelevent 
     if($url_path_length <> count($filter)) 
     { 
      continue; 
     } 

     foreach($filter as $i => $key) 
     { 
      if(strpos($key, ':') === 0) 
      { 
       $parameters[substr($key, 1)] = $url_path[$i]; 
      } 
      // this filter is irrelevent 
      else if($key != $url_path[$i]) 
      {  
       continue 2; 
      } 
     } 

     $final_path = $original_path; 

     break; 
    } 

    return $final_path ? array('path' => $final_path, 'parameters' => $parameters) : FALSE; 
} 

die(var_dump(ay_dispatcher('page/edit', $routes), ay_dispatcher('page/edit/12', $routes), ay_dispatcher('random/invalid/url', $routes))); 

出力:

array(2) { 
    ["path"]=> 
    string(3) "bar" 
    ["parameters"]=> 
    array(1) { 
    ["action"]=> 
    string(4) "edit" 
    } 
} 
array(2) { 
    ["path"]=> 
    string(3) "foo" 
    ["parameters"]=> 
    array(2) { 
    ["action"]=> 
    string(4) "edit" 
    ["id"]=> 
    string(2) "12" 
    } 
} 
bool(false) 
+0

私はこのソリューションが好きです!おそらく、私はZend Frameworkをあまりにも多く模倣するのをやめてください。しかし、おそらく初心者のために、regexメソッドは$ routes配列を少し読みやすくします。 – Dan

+0

$ルートを自分のフォーマットに変換するには1行のコードが必要です。 'array_map(funciton($ e){return explode( '/'、$ e);} $ your_routes)'です。 – Gajus

+0

更新されたバージョンはhttp://meta.codereview.stackexchange.com/questions/411/regexless-dispatcher – Gajus