8

PHP Web サービスのルーティングを処理するクラスを作成していますが、正規表現を修正する必要があり、URL を解析する最も効率的な方法を知りたいです。

URL の例:

  • ポスト/ユーザー
  • GET /ユーザー
  • GET /ユーザー&制限=10&オフセット=0
  • GET /users/search&keyword=リチャード
  • GET /users/15/posts/38

クラス用にPHPで作成したいのはこれです:

$router = new Router();
$router->addRoute('POST', '/users', function(){});
$router->addRoute('GET', '/users/:uid/posts/:pid', function($uid, $pid){});
$target = $router->doRouting();

ターゲット変数には、次の配列が含まれます。

  • 方法
  • URL
  • コールバック メソッド

これは私がこれまでに得たものです:

class Router{
    use Singleton;

    private $routes = [];
    private $routeCount = 0;

    public function addRoute($method, $url, $callback){
        $this->routes[] = ['method' => $method, 'url' => $url, 'callback' => $callback];
        $this->routeCount++;
    }

    public function doRouting(){
        $reqUrl = $_SERVER['REQUEST_URI'];
        $reqMet = $_SERVER['REQUEST_METHOD'];

        for($i = 0; $i < $this->routeCount; $i++){
            // Check if the url matches ...
            // Parse the arguments of the url ...
        }
    }
}

したがって、まず最初に次の正規表現が必要です。

  1. /mainAction/:引数名/secondaryAction/:secondaryActionName

それが $reqUrl と一致するかどうかを確認します (上記の for ループを参照)

  1. 引数を抽出して、コールバック関数で使用できるようにします。

私が自分で試したこと:

(code should be in the for loop @ doRouting function)

// Extract arguments ...
$this->routing[$i]['url'] = str_replace(':arg', '.+', $this->routing[$i]['url']);

// Does the url matches the routing url?
if(preg_match('#^' . $this->routes[$i]['url'] . '$#', $reqUrl)){
    return $this->routes[$i];
}

すべての助けに本当に感謝しています、どうもありがとう。

4

2 に答える 2

11

これは基本的に機能します。

public function doRouting(){
    // I used PATH_INFO instead of REQUEST_URI, because the 
    // application may not be in the root direcory
    // and we dont want stuff like ?var=value
    $reqUrl = $_SERVER['PATH_INFO'];
    $reqMet = $_SERVER['REQUEST_METHOD'];

    foreach($this->routes as  $route) {
        // convert urls like '/users/:uid/posts/:pid' to regular expression
        $pattern = "@^" . preg_replace('/\\\:[a-zA-Z0-9\_\-]+/', '([a-zA-Z0-9\-\_]+)', preg_quote($route['url'])) . "$@D";
        $matches = Array();
        // check if the current request matches the expression
        if($reqMet == $route['method'] && preg_match($pattern, $reqUrl, $matches)) {
            // remove the first match
            array_shift($matches);
            // call the callback with the matched positions as params
            return call_user_func_array($route['callback'], $matches);
        }
    }
}

$routeCountPS:属性は必要ありません

于 2012-07-30T14:03:51.583 に答える