Heim >Backend-Entwicklung >PHP-Tutorial >php url 调度
1, 支持非rewrite即: http://localhost/index.php/blog/view/5456-asdf.html 也可以被正确解析。。 ----------------------------------- 2,增加:绝对地址生成 只要 rurl('myFirstRouter', array('id' => '33', 'name' => 'thename'), true); 最后多加一个true,默认为false即相对地址。 生成绝对地址如:网站根目录/fleaphp/test/blog/view/33-thename.html 修改自ZendFramework的Router_Regexp类。 花了点时间整理的,水平有限,希望有高人能完善一下。 定义一个路由跟定义DSN一样的方法:
return array( 'routers' =>array( 'myFirstRouter' => array( 'blog/view(?:/(\d+)-(.+))\.html', array( 'id' => '1', 'controller' => 'default', 'action' => 'index' ), array( 1 => 'id', 2 => 'name' ), 'blog/view/%d-%s.html' ), 'mySecondRouter' => array( 'blog(?:/(\d+)-(.+))\.html', array( 'id' => '1', 'controller' => 'default', 'action' => 'index' ), array( 1 => 'id', 2 => 'name' ), 'blog/%d-%s.html' ), 'myThirdRouter' => array( '([a-z0-9]+)/([a-z0-9]+)', array(), array( 1 => 'controller', 2 => 'action' ), 'blog/%d-%s.html' ) ) ); 复制代码 是一个二维数组,每一个值为一条路由规则。其中第一项是正则表达式,第二项为:参数默认值(这里可以设置controller,action,及其它参数的默认值。) 第三项为:参数的对应关系,与第一项的正则表达里面匹配元素对应。 第四项用于生成链接时候使用的格式。如果没看明白,可以看ZF的Router一节。 先发改的My_Dispatcher_Regexp类的代码:
loadRouters(); if (! is_array($this->_routers)) return false; if (!$this->_pathInfo) $this->getPathInfo(); foreach (array_reverse($this->_routers) as $router) { if (! is_array($router)) continue; if ($router[0] == '' || !is_string($router[0])) continue; $regexp = '#^' . $router[0]. '$#i'; if (! isset($router[1])) $router[1] = array(); if (! isset($router[2])) $router[2] = array(); if ($args = $this->match($regexp, $this->_pathInfo, $router[1], $router[2])) { $this->_curRouter = $router; $data['controller'] = $args['controller']; $data['action'] = $args['action']; $_GET = array_merge($_GET, $args); break; } } $this->_request = $data; } /** * 载入路由数据信息 * */ function loadRouters() { static $routerLoaded; if ($routerLoaded) return; $routerLoaded = false; $routerConfig = FLEA::getAppInf('routerConfig'); FLEA::loadAppInf($routerConfig); $this->_routers = FLEA::getAppInf('routers'); $routerLoaded = true; } /** * 根据服务器环境不同,取得RequestUri信息 * * @return unknown */ function getRequestUri() { if ($this->_requestUri) return $this->_requestUri; if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch $requestUri = $_SERVER['HTTP_X_REWRITE_URL']; } elseif (isset($_SERVER['REQUEST_URI'])) { $requestUri = $_SERVER['REQUEST_URI']; } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI $requestUri = $_SERVER['ORIG_PATH_INFO']; if (!empty($_SERVER['QUERY_STRING'])) { $requestUri .= '?' . $_SERVER['QUERY_STRING']; } } else { $requestUri = null; } $this->_requestUri = $requestUri; return $requestUri; } function getBaseUrl() { if ($this->_baseUrl) return $this->_baseUrl; $filename = basename($_SERVER['SCRIPT_FILENAME']); if (basename($_SERVER['SCRIPT_NAME']) === $filename) { $baseUrl = $_SERVER['SCRIPT_NAME']; } elseif (basename($_SERVER['PHP_SELF']) === $filename) { $baseUrl = $_SERVER['PHP_SELF']; } elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $filename) { $baseUrl = $_SERVER['ORIG_SCRIPT_NAME']; // 1and1 shared hosting compatibility } else { // Backtrack up the script_filename to find the portion matching // php_self $path = $_SERVER['PHP_SELF']; $segs = explode('/', trim($_SERVER['SCRIPT_FILENAME'], '/')); $segs = array_reverse($segs); $index = 0; $last = count($segs); $baseUrl = ''; do { $seg = $segs[$index]; $baseUrl = '/' . $seg . $baseUrl; ++$index; } while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos)); } // Does the baseUrl have anything in common with the request_uri? $requestUri = $this->getRequestUri(); if (0 === strpos($requestUri, $baseUrl)) { // full $baseUrl matches $this->_baseUrl = $baseUrl; return $this->_baseUrl; } if (0 === strpos($requestUri, dirname($baseUrl))) { // directory portion of $baseUrl matches $baseUrl = rtrim(dirname($baseUrl), '/'); $this->_baseUrl = $baseUrl; return $this->_baseUrl; } if (!strpos($requestUri, basename($baseUrl))) { // no match whatsoever; set it blank $this->_baseUrl = ''; return $this->_baseUrl; } // If using mod_rewrite or ISAPI_Rewrite strip the script filename // out of baseUrl. $pos !== 0 makes sure it is not matching a value // from PATH_INFO or QUERY_STRING if ((strlen($requestUri) >= strlen($baseUrl)) && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0))) { $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl)); } $baseUrl = rtrim($baseUrl, '/'); $this->_baseUrl = $baseUrl; return $this->_baseUrl; } function getPathInfo () { $baseUrl = $this->getBaseUrl(); if (null === ($requestUri = $this->getRequestUri())) { return null; } // Remove the query string from REQUEST_URI if ($pos = strpos($requestUri, '?')) { $requestUri = substr($requestUri, 0, $pos); } if ((null !== $baseUrl) && (false === ($pathInfo = substr($requestUri, strlen($baseUrl))))) { // If substr() returns false then PATH_INFO is set to an empty string $pathInfo = ''; } elseif (null === $baseUrl) { $pathInfo = $requestUri; } $this->_pathInfo = $pathInfo; return $pathInfo; } /** * Matches a user submitted path with a previously defined route. * Assigns and returns an array of defaults on a successful match. * * @param string Path used to match against this routing map * @return array|false An array of assigned values or a false on a mismatch */ function match($regex, $path, $defaults, $map) { $path = trim(urldecode($path), '/'); $res = preg_match($regex, $path, $values); if ($res === 0) return false; foreach ($values as $i => $value) { if (!is_int($i) || $i === 0) { unset($values[$i]); } } $values = $this->_getMappedValues($map, $values); $defaults = $this->_getMappedValues($map, $defaults, false, true); $return = $values + $defaults; return $return; } /** * Maps numerically indexed array values to it's associative mapped counterpart. * Or vice versa. Uses user provided map array which consists of index => name * parameter mapping. If map is not found, it returns original array. * * Method strips destination type of keys form source array. Ie. if source array is * indexed numerically then every associative key will be stripped. Vice versa if reversed * is set to true. * * @param array Indexed or associative array of values to map * @param boolean False means translation of index to association. True means reverse. * @param boolean Should wrong type of keys be preserved or stripped. * @return array An array of mapped values */ function _getMappedValues($map, $values, $reversed = false, $preserve = false) { if (count($map) == 0) { return $values; } $return = array(); foreach ($values as $key => $value) { if (is_int($key) && !$reversed) { if (array_key_exists($key, $map)) { $index = $map[$key]; } elseif (false === ($index = array_search($key, $map))) { $index = $key; } $return[$index] = $values[$key]; } elseif ($reversed) { $index = (!is_int($key)) ? array_search($key, $map, true) : $key; if (false !== $index) { $return[$index] = $values[$key]; } } elseif ($preserve) { $return[$key] = $value; } } return $return; } /** * Assembles a URL path defined by this route * * @param array An array of name (or index) and value pairs used as parameters * @return string Route path with user submitted parameters */ function assemble($defaults, $map = array(), $reverse, $data = array()) { if ($reverse === null) { return '构建网址失败!路由参数错误!'; } $data = $this->_getMappedValues($map, $data, true, false); $data += $this->_getMappedValues($map, $defaults, true, false); //$data += $this->_values; ksort($data); $return = @vsprintf($reverse, $data); if ($return === false) { return '构建网址失败!'; } return $return; } /** * 使用路由构建网址 */ function url($routerName, $urlOptions, $absolute) { $this->loadRouters(); if (isset($this->_routers[$routerName])) $curRouter = $this->_routers[$routerName]; elseif (isset($this->_curRouter)) $curRouter = $this->_curRouter; if (is_array($curRouter) && count($curRouter) == 4 && is_string($curRouter[3])) { $defaults = $curRouter[1]; $map = $curRouter[2]; $reverse = $curRouter[3]; } else { return '构建网址失败!路由参数错误!'; } if (is_array($map) && is_string($reverse)) if (!$absolute) return $this->assemble($defaults, $map, $reverse, $urlOptions); else { if (!$this->_baseUrl) $this->getBaseUrl(); return $this->_baseUrl . '/' .$this->assemble($defaults, $map, $reverse, $urlOptions); } } } 复制代码 这里要说一个比较好的自定义类的命名规则及文件放置位置。在FLEA下面建一个My的目录里面放自已的类。比如My_Dispatcher_Regexp放在: My/Dispatcher/Regexp.php 同时为方便写一个生成网址助手: My_Helper_Router My/Helper/Router.php 代码如下:
url($routerName, $urlOptions, $absolute); } 复制代码 使用方法:/* 修改默认的Dispatcher为自定义的Dispatcher类*/ FLEA::setAppInf('dispatcher','My_Dispatcher_Regexp'); /* 设置路由配置信息的文件位置*/ FLEA::setAppInf('routerConfig', './APP/config/router.php'); 其它代码跟任何一个普通的例子一样。 controller里面代码如下:
复制代码 我们在view中用下面代码:
'33', 'name' => 'thename')); 复制代码 就可以看到$_GET得到正确的参数,rurl也生成我们期望的网址: blog/view/33-thename.html 绝对网址生成方法如下:
rurl('myFirstRouter', array('id' => '33', 'name' => 'thename'),true); //将生成如下的网址: /other/fleaphp/test/blog/view/33-thename.html 如果没有使用apache的mod_rewrite功能生成的网址如下: /fleaphp/test/index.php/blog/view/33-thename.html |