Beispiel #1
2
 /**
  * 测试反向解析
  */
 function testReservedParse()
 {
     $context = QContext::instance();
     $router = new QRouter($context);
     foreach ($this->_tests_args as $offset => $test) {
         $copy = $test;
         $path = $test['_path'];
         unset($test['_path']);
         $context->module_name = isset($test['module']) ? $test['module'] : null;
         $context->namespace = isset($test['namespace']) ? $test['namespace'] : null;
         $context->controller_name = isset($test['controller']) ? $test['controller'] : null;
         $context->action_name = isset($test['action']) ? $test['action'] : null;
         $context->setRequestUDI();
         $test['module'] = $context->module_name;
         $test['namespace'] = $context->namespace;
         $test['controller'] = $context->controller_name;
         $test['action'] = $context->action_name;
         $result = $router->url($test);
         list($route_name) = explode(':', $offset);
         if ($route_name != $router->reserve_matched_route_name) {
             QDebug::dump($test, "Expected route name is [{$offset}] : {$path}.");
         }
         $this->assertEquals($route_name, $router->reserve_matched_route_name, "Expected route name is [{$route_name}].");
         $this->assertEquals($path, $result, print_r($copy, true) . "\n" . print_r($test, true));
     }
 }
Beispiel #2
0
 /**
  * 测试反向解析
  */
 function testReverseParse()
 {
     $context = QContext::instance();
     $router = new QRouter();
     $router->import(Q::ini('routes'));
     foreach ($this->_tests_args as $offset => $test) {
         $copy = $test;
         $path = $test['_path'];
         unset($test['_path']);
         $result = $router->url($test);
         list($route_name) = explode(':', $offset);
         if ($route_name != $router->lastReverseMatchedRouteName()) {
             dump('-----------------------------------');
             dump($path, 'test path');
             dump($test, $result);
             dump($router->lastReverseMatchedRouteName(), 'used route');
             dump($route_name, 'expected route');
             dump($router->get($route_name));
         }
         $this->assertEquals($route_name, $router->lastReverseMatchedRouteName(), "Expected route name is [{$route_name}].");
         $this->assertEquals($path, $result, "{$path} == {$result}\n" . print_r($copy, true) . "\n" . print_r($test, true));
     }
 }
Beispiel #3
0
 /**
  * 构造 url
  *
  * 用法:
  *
  * @code php
  * url(UDI, [附加参数数组], [路由名])
  * @endcode
  *
  * UDI 是统一目的地标识符(Uniform Destination Identifier)的缩写。
  * UDI 由控制器、动作、名字空间以及模块名组成,采用如下的格式:
  *
  * @code php
  * ns::controller/action@module
  * @endcode
  *
  * UDI 字符串中,每一个部分都是可选的。
  * 如果没有提供控制器和动作名,则使用当前的控制器和默认动作名(index)代替。
  * 同样,如果未提供模块名和名字空间,均使用当前值代替。
  *
  * UDI 字符串写法示例:
  *
  * @code php
  * 'controller'
  * 'controller/action'
  * '/action'
  * 'controller@module'
  * 'controller/action@module'
  * 'ns::controller'
  * 'ns::controller/action'
  * 'ns::controller@module'
  * 'ns::controller/action@module'
  * '@module'
  * 'ns::@module'
  * @endcode
  *
  * 示例:
  * @code php
  * url('admin::posts/edit', array('id' => $post->id()));
  * @endcode
  *
  * $params 参数除了采用数组,还可以是以“/”符号分割的字符串:
  *
  * @code php
  * url('posts/index', 'page/3');
  * url('users/show', 'id/5/profile/yes');
  * @endcode
  *
  * 在使用 PATHINFO 和 URL 重写时,可以使用通过制定路由名来强制要求 QeePHP
  * 采用指定的路由规则来生成 URL。强制指定路由规则可以加快 URL 的生成,
  * 但在路由规则名称发生变化时,需要修改生成 URL 的代码。
  *
  * $opts 参数用于控制如何生成 URL。可用的选项有:
  *
  * -  base_uri: 指定 URL 前部要添加的路径(可以包括协议、域名和端口,以及路径)
  * -  script: 指定 URL 前部要使用的脚本名
  * -  mode: 指定 URL 生成模式,可以是 standard、pathinfo 和 rewrite
  *
  * @param string $udi UDI 字符串
  * @param array|string $params 附加参数数组
  * @param string $route_name 路由名
  * @param array $opts 控制如何生成 URL 的选项
  *
  * @return string 生成的 URL 地址
  */
 function url($udi, $params = null, $route_name = null, array $opts = null)
 {
     static $base_uri;
     if (is_null($base_uri)) {
         if (strlen(Q::ini('base_uri')) > 0) {
             $base_uri = Q::ini('base_uri');
         } else {
             $base_uri = '/' . trim($this->baseDir(), '/');
             if ($base_uri != '/') {
                 $base_uri .= '/';
             }
         }
     }
     $udi = $this->normalizeUDI($udi);
     if (!is_array($params)) {
         $arr = Q::normalize($params, '/');
         $params = array();
         while ($key = array_shift($arr)) {
             $value = array_shift($arr);
             $params[$key] = $value;
         }
     }
     $params = array_filter($params, 'strlen');
     // 处理 $opts
     if (is_array($opts)) {
         $mode = !empty($opts['mode']) ? $opts['mode'] : self::$_url_mode;
         $script = !empty($opts['script']) ? $opts['script'] : $this->scriptName();
         $url = strlen($opts['base_uri']) > 0 ? rtrim($opts['base_uri'], '/') . '/' : $base_uri;
     } else {
         $mode = self::$_url_mode;
         $url = $base_uri;
         $script = $this->scriptName();
     }
     if (!is_null($this->_router) && $mode != self::URL_MODE_STANDARD) {
         // 使用路由生成 URL
         $params = array_merge($params, $udi);
         $path = $this->_router->url($params, $route_name);
         if (self::$_url_mode == self::URL_MODE_PATHINFO && $path != '/') {
             $url .= $this->scriptName();
         } else {
             $url = rtrim($url, '/');
         }
         $url .= $path;
     } else {
         foreach (self::$_udi_defaults as $key => $value) {
             if ($udi[$key] == $value) {
                 unset($udi[$key]);
             }
             unset($params[$key]);
         }
         $params = array_filter(array_merge($udi, $params), 'strlen');
         $url .= $script;
         if (!empty($params)) {
             $url .= '?' . http_build_query($params, '', '&');
         }
     }
     return $url;
 }
Beispiel #4
0
 /**
  * 构造 url
  *
  * url() 方法支持多种调用模式,分别是:
  *
  * <ul>
  *   <li>url([控制器名], [动作名], [附加参数数组], [名字空间], [模块名], [路由名])</li>
  *   <li>url(UDI, [附件参数数组], [路由名])</li>
  *   <li>url(参数数组, [路由名])</li>
  * </ul>
  *
  * UDI 是统一目的地标识符(Uniform Destination Identifier)的缩写。
  *
  * UDI 由控制器、动作、名字空间以及模块名组成,采用如下的格式:
  *
  * namespace::controller/action@module
  *
  * 如果没有提供 namespace 和 module,则 controller 是必须提供的。
  *
  * 可以有下列写法:
  *
  * 'controller'
  * 'controller/action'
  * '/action'
  * 'controller@module'
  * 'controller/action@module'
  * 'namespace::controller'
  * 'namespace::controller/action'
  * 'namespace::controller@module'
  * 'namespace::controller/action@module'
  * '@module'
  * 'namespace::@module'
  *
  * @param string $controller_name
  * @param string $action_name
  * @param array $params
  * @param string $namespace
  * @param string $module
  * @param string $route_name
  *
  * @return string
  */
 function url($controller_name = null, $action_name = null, $params = null, $namespace = null, $module = null, $route_name = null)
 {
     static $base_uri;
     if (is_null($base_uri)) {
         $base_uri = $this->getProtocol() . '://' . rtrim($_SERVER['SERVER_NAME'], '/');
         $server_port = $this->getServerPort();
         if ($server_port != 80) {
             $base_uri .= ":{$server_port}";
         }
         $base_uri .= '/' . ltrim($this->getBaseDir(), '/');
     }
     $controller_accessor = $this->getIni('dispatcher_controller_accessor');
     $action_accessor = $this->getIni('dispatcher_action_accessor');
     $namespace_accessor = $this->getIni('dispatcher_namespace_accessor');
     $module_accessor = $this->getIni('dispatcher_module_accessor');
     if (is_array($controller_name)) {
         // 模式3: url(参数数组, [路由名])
         $url_args = $controller_name;
         $route_name = $action_name;
         if (isset($url_args['namespace']) || isset($url_args[$namespace_accessor])) {
             $namespace = isset($url_args['namespace']) ? $url_args['namespace'] : $url_args[$namespace_accessor];
             unset($url_args['namespace']);
             unset($url_args[$namespace_accessor]);
         } else {
             $namespace = $this->namespace;
         }
         if (isset($url_args['module']) || isset($url_args[$module_accessor])) {
             $module = isset($url_args['module']) ? $url_args['module'] : $url_args[$module_accessor];
             unset($url_args['module']);
             unset($url_args[$module_accessor]);
         } else {
             $module = $this->module;
         }
         if (isset($url_args['controller']) || isset($url_args[$controller_accessor])) {
             $controller_name = isset($url_args['controller']) ? $url_args['controller'] : $url_args[$controller_accessor];
             unset($url_args['controller']);
             unset($url_args[$controller_accessor]);
         } else {
             $controller_name = $this->controller_name;
         }
         if (isset($url_args['action']) || isset($url_args[$action_accessor])) {
             $action_name = isset($url_args['action']) ? $url_args['action'] : $url_args[$action_accessor];
             unset($url_args['action']);
             unset($url_args[$action_accessor]);
         } else {
             $action_name = null;
         }
         $params = $url_args;
     } else {
         $destinfo = $this->destinfo($controller_name);
         if (is_array($action_name)) {
             // 模式2: url(UDI, [附件参数数组], [路由名])
             $module = $destinfo[self::DESTINFO_MODULE];
             $namespace = $destinfo[self::DESTINFO_NAMESPACE];
             $controller_name = $destinfo[self::DESTINFO_CONTROLLER];
             $route_name = $params;
             $params = $action_name;
             $action_name = $destinfo[self::DESTINFO_ACTION];
         } else {
             // 模式1: url([控制器名], [动作名], [附加参数数组], [名字空间], [模块名], [路由名])
             if (is_null($module)) {
                 $module = $destinfo[self::DESTINFO_MODULE];
             }
             if (is_null($namespace)) {
                 $namespace = $destinfo[self::DESTINFO_NAMESPACE];
             }
             $controller_name = $destinfo[self::DESTINFO_CONTROLLER];
             if (is_null($action_name)) {
                 $action_name = $destinfo[self::DESTINFO_ACTION];
             }
         }
     }
     // 确定控制器和动作的名字
     $controller_name = empty($controller_name) ? $this->getIni('dispatcher_default_controller') : $controller_name;
     $action_name = empty($action_name) ? $this->getIni('dispatcher_default_action') : $action_name;
     $controller_name = strtolower($controller_name);
     $action_name = strtolower($action_name);
     $url_args = array();
     if (!is_null($this->_router)) {
         $module_accessor = 'module';
         $namespace_accessor = 'namespace';
         $controller_accessor = 'controller';
         $action_accessor = 'action';
     }
     if ($module) {
         $url_args[$module_accessor] = $module;
     }
     if ($namespace) {
         $url_args[$namespace_accessor] = $namespace;
     }
     $url_args[$controller_accessor] = $controller_name;
     $url_args[$action_accessor] = $action_name;
     if (is_array($params) && !empty($params)) {
         $url_args = array_merge($url_args, $params);
     }
     if (!is_null($this->_router)) {
         $url = rtrim($base_uri, '/');
         if (self::$_url_mode == self::URL_MODE_PATHINFO) {
             $url .= '/' . $this->getScriptName();
         }
         $url .= $this->_router->url($url_args, $route_name);
     } else {
         $url = rtrim($base_uri, '/') . '/' . $this->getScriptName() . '?' . http_build_query($url_args, '', '&');
     }
     return $url;
 }
 /**
  * 构造 url
  *
  * 用法:
  *
  * @code php
  * url(UDI, [附加参数数组], [路由名])
  * @endcode
  *
  * UDI 是统一目的地标识符(Uniform Destination Identifier)的缩写。
  * UDI 由控制器、动作、名字空间以及模块名组成,采用如下的格式:
  *
  * @code php
  * namespace::controller/action@module
  * @endcode
  *
  * UDI 字符串中,每一个部分都是可选的。
  * 如果没有提供控制器和动作名,则使用当前的控制器和默认动作名(index)代替。
  * 同样,如果未提供模块名和名字空间,均使用当前值代替。
  *
  * UDI 字符串写法示例:
  *
  * @code php
  * 'controller'
  * 'controller/action'
  * '/action'
  * 'controller@module'
  * 'controller/action@module'
  * 'namespace::controller'
  * 'namespace::controller/action'
  * 'namespace::controller@module'
  * 'namespace::controller/action@module'
  * '@module'
  * 'namespace::@module'
  * @endcode
  *
  * 示例:
  * @code php
  * url('admin::posts/edit', array('id' => $post->id()));
  * @endcode
  *
  * 在使用 PATHINFO 和 URL 重写时,可以使用通过制定路由名来强制要求 QeePHP
  * 采用指定的路由规则来生成 URL。强制指定路由规则可以加快 URL 的生成,
  * 但在路由规则名称发生变化时,需要修改生成 URL 的代码。
  *
  * @param string $udi UDI 字符串
  * @param array $params 附加参数数组
  * @param string $route_name 路由名
  *
  * @return string 生成的 URL 地址
  */
 function url($udi, array $params = null, $route_name = null)
 {
     static $base_uri;
     if (is_null($base_uri)) {
         $base_uri = $this->protocol() . '://' . rtrim($_SERVER['SERVER_NAME'], '/');
         $server_port = $this->serverPort();
         if ($server_port != 80) {
             $base_uri .= ":{$server_port}";
         }
         $base_uri .= '/' . ltrim($this->baseDir(), '/');
     }
     $udi = $this->normalizeUDI($udi);
     if (!is_array($params)) {
         $params = array();
     }
     if (!is_null($this->_router)) {
         // 使用路由生成 URL
         $url = rtrim($base_uri, '/');
         if (self::$_url_mode == self::URL_MODE_PATHINFO) {
             $url .= '/' . $this->scriptName();
         }
         $params = array_merge($params, $udi);
         $url .= $this->_router->url($params, $route_name);
     } else {
         foreach (self::$_udi_defaults as $key => $value) {
             if ($udi[$key] == $value) {
                 unset($udi[$key]);
             }
             unset($params[$key]);
         }
         $params = array_filter(array_merge($udi, $params));
         $url = rtrim($base_uri, '/') . '/' . $this->scriptName() . '?';
         $url .= http_build_query($params, '', '&');
     }
     return $url;
 }