예제 #1
0
파일: Router.php 프로젝트: ksst/kf
 /**
  * Matches the URI against the Routes Mapping Table.
  * Taking static, dynamic and regexp routings into account.
  * In other words, it "map matches the URI".
  *
  * @return TargetRoute|null
  */
 public function match()
 {
     // do we have some routes now?
     if (0 === count($this->routes)) {
         throw new \OutOfBoundsException('The routes lookup table is empty. Define some routes.');
     }
     /*
      * Detects if Mod_Rewrite engine is active and
      * calls the proper URL Parser/Segmentizer method for the extraction of uri segments.
      */
     if ($this->isRewriteEngineOn() or isset($_ENV['FORCE_MOD_REWRITE_ON']) and true === empty($_GET['mod']) and true === empty($_GET['ctrl'])) {
         $this->uriSegments = $this->parseUrlRewrite($this->uri);
     } else {
         $this->uriSegments = $this->parseUrlNoRewrite($this->uri);
         $this->uriSegments = self::fixNoRewriteShorthands($this->uriSegments);
         $targetRoute = TargetRoute::setSegmentsToTargetRoute($this->uriSegments);
         if ($targetRoute::dispatchable()) {
             return $targetRoute;
         }
     }
     /*
      * Reduce the map lookup table, by dropping all routes
      * with more segments than the current requested uri.
      */
     if (count($this->routes) > 1 and count($this->uriSegments) >= 1) {
         self::reduceRoutesToSegmentCount();
     }
     /*
      * Process:     Static Route
      *
      * Do we have a direct match ?
      * This matches "static routes". Without any preg_match overhead.
      *
      * Example:
      * The request URI "/news/index" relates 1:1 to $routes['/news/index'].
      * The request URI "/login"      relates 1:1 to $routes['/login']
      */
     if (isset($this->routes[$this->uri])) {
         // we have a direct match
         $found_route = $this->routes[$this->uri];
         // return the TargetRoute object
         return TargetRoute::setSegmentsToTargetRoute($found_route);
     } else {
         /*
          * No, there wasn't a 1:1 match.
          * Now we have to check the uri segments.
          *
          * Let's loop over the remaining routes and try to map match the uri_segments.
          */
         foreach ($this->routes as $route_pattern => $route_values) {
             unset($route_pattern);
             $matches = '';
             /**
              * Process:     Dynamic Regular Expression Parameters.
              *
              * Example:
              * URI: /news
              * Rule /:controller
              * Regexp: "#(?P<controller>[a-z0-9_-]+)\/?#"
              * Matches: $matches['controller'] = 'news';
              */
             if (1 === preg_match($route_values['regexp'], $this->uri, $matches)) {
                 // matches[0] contains $this->uri
                 unset($matches[0]);
                 // remove duplicate values
                 // e.g. [controller] = news
                 //      [1]          = news
                 $matches = array_unique($matches);
                 # @todo # fetch key and its position from $route_values['requirements']
                 if (count($route_values['requirements']) > 0) {
                     foreach ($route_values['requirements'] as $array_position => $key_name) {
                         // insert a new key
                         // with name from requirements array
                         // and value from matches array
                         // ([id] => 42)
                         $pos = $array_position + 1;
                         $matches[$key_name] = $matches[$pos];
                         // remove the old not-named key ([2] => 42)
                         unset($matches[$pos]);
                     }
                 }
                 // insert $matches[<controller>] etc
                 TargetRoute::setSegmentsToTargetRoute($matches);
             }
             if (TargetRoute::dispatchable()) {
                 // route found, stop foreach
                 break;
             } else {
                 TargetRoute::reset();
                 continue;
             }
         }
     }
     return TargetRoute::instantiate();
 }