/** * 测试反向解析 */ 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)); } }
/** * 测试反向解析 */ 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)); } }
/** * 构造 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; }
/** * 根据 php.ini 中的 magic quotes gpc 设置去除超全局变量中自动添加的转义符 */ private function _initOneTime() { if (self::$_root) { return; } self::$_root = $this; // 禁止 magic quotes set_magic_quotes_runtime(0); // 处理被 magic quotes 自动转义过的数据 if (get_magic_quotes_gpc()) { $in = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST); while (list($k, $v) = each($in)) { foreach ($v as $key => $val) { if (!is_array($val)) { $in[$k][$key] = stripslashes($val); continue; } $in[] =& $in[$k][$key]; } } unset($in); } $url_mode = strtolower($this->getIni('dispatcher_url_mode')); if ($url_mode == self::URL_MODE_PATHINFO || $url_mode == self::URL_MODE_REWRITE) { $this->_router = new QRouter($this); $result = $this->_router->match($this->getPathinfo()); if ($result) { foreach ($result as $var => $value) { if (empty($_GET[$var])) { $_GET[$var] = $_REQUEST[$var] = $value; } } } self::$_url_mode = $url_mode; } else { self::$_url_mode = self::URL_MODE_STANDARD; $this->_router = null; } }
/** * 构造 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; }