zoukankan      html  css  js  c++  java
  • 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一样的方法:
    1. return array(
    2. 'routers' =>array(
    3.   'myFirstRouter' => array(
    4.    'blog/view(?:/(\d+)-(.+))\.html',
    5.    array(
    6.     'id'   => '1',
    7.     'controller'  => 'default',
    8.     'action'  => 'index'
    9.    ),
    10.    array(
    11.     1 => 'id',
    12.     2 => 'name'
    13.    ),
    14.    'blog/view/%d-%s.html'
    15.   ),
    16.   'mySecondRouter' => array(
    17.    'blog(?:/(\d+)-(.+))\.html',
    18.    array(
    19.     'id'   => '1',
    20.     'controller'  => 'default',
    21.     'action'  => 'index'
    22.    ),
    23.    array(
    24.     1 => 'id',
    25.     2 => 'name'
    26.    ),
    27.    'blog/%d-%s.html'
    28.   ),
    29.   'myThirdRouter' => array(
    30.    '([a-z0-9]+)/([a-z0-9]+)',
    31.    array(),
    32.    array(
    33.     1 => 'controller',
    34.     2 => 'action'
    35.    ),
    36.    'blog/%d-%s.html'
    37.   )  
    38. )
    39. );
    复制代码
    是一个二维数组,每一个值为一条路由规则。
    其中第一项是正则表达式,第二项为:参数默认值(这里可以设置controller,action,及其它参数的默认值。)
    第三项为:参数的对应关系,与第一项的正则表达里面匹配元素对应。
    第四项用于生成链接时候使用的格式。如果没看明白,可以看ZF的Router一节。

    先发改的My_Dispatcher_Regexp类的代码:
    1. <?php
    2. /**
    3. * Zend Framework
    4. *
    5. * LICENSE
    6. *
    7. * This source file is subject to the new BSD license that is bundled
    8. * with this package in the file LICENSE.txt.
    9. * It is also available through the world-wide-web at this URL:
    10. * http://framework.zend.com/license/new-bsd
    11. * If you did not receive a copy of the license and are unable to
    12. * obtain it through the world-wide-web, please send an email
    13. * to license@zend.com so we can send you a copy immediately.
    14. *
    15. * @package    Zend_Controller
    16. * @subpackage Router
    17. * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
    18. * @version    $Id$
    19. * @license    http://framework.zend.com/license/new-bsd     New BSD License
    20. */
    21. // {{{ includes
    22. FLEA::loadClass('FLEA_Dispatcher_Simple');
    23. // }}}
    24. /**
    25. * My_Dispatcher_Regexp
    26. *
    27. * @package My_Dispatcher
    28. * @author tg8866
    29. * @version 0.01
    30. */
    31. class My_Dispatcher_Regexp extends FLEA_Dispatcher_Simple
    32. {
    33.     /**
    34.      * 保存路由信息的数组(二级数组)
    35.      *
    36.      * @var array
    37.      */
    38.     var $_routers;
    39.     
    40.     /**
    41.      * 当前浏览页面的路由信息
    42.      *
    43.      * @var array (一维数组)
    44.      */
    45.     var $_curRouter;
    46.     
    47.     /**
    48.      * 保存baseurl信息
    49.      *
    50.      * @var string
    51.      */
    52.     var $_baseUrl;
    53.     
    54.     /**
    55.      * 保存requestURI信息
    56.      *
    57.      * @var string
    58.      */
    59.     var $_requestUri;
    60.     
    61.     /**
    62.      * 可用的路径信息 不包括 子目录信息 
    63.      * 比如:http://localhost/index.php 是主页
    64.      * 则 http://localhost/blog/view/123-abc.html
    65.      * 的路径信息为: /blog/view/123-abc.html
    66.      * @var unknown_type
    67.      */
    68.     var $_pathInfo;
    69.     /**
    70.      * 构造函数
    71.      *
    72.      * @param array $request
    73.      *
    74.      * @return My_Dispatcher_Regexp
    75.      */
    76.     function My_Dispatcher_Regexp(& $request)
    77.     {
    78.         parent::FLEA_Dispatcher_Simple($request);
    79.         
    80.         $this->loadRouters();
    81.         if (! is_array($this->_routers)) return false;
    82.         if (!$this->_pathInfo) $this->getPathInfo();
    83.         
    84.         foreach (array_reverse($this->_routers) as $router) {
    85.          if (! is_array($router)) continue;
    86.          if ($router[0] == '' || !is_string($router[0])) continue;
    87.          $regexp = '#^' . $router[0]. '$#i';
    88.    if (! isset($router[1])) $router[1] = array();
    89.          if (! isset($router[2])) $router[2] = array();
    90.          if ($args = $this->match($regexp, $this->_pathInfo, $router[1], $router[2])) {
    91.           $this->_curRouter = $router;
    92.           $data['controller'] = $args['controller'];
    93.           $data['action'] = $args['action'];
    94.           $_GET = array_merge($_GET, $args);
    95.           break;
    96.          }
    97.         }
    98.         $this->_request = $data;
    99.     }
    100.     /**
    101.      * 载入路由数据信息
    102.      *
    103.      */
    104.     function loadRouters() {
    105.      static $routerLoaded;
    106.      if ($routerLoaded) return;
    107.      $routerLoaded = false;
    108.      $routerConfig = FLEA::getAppInf('routerConfig');
    109.         FLEA::loadAppInf($routerConfig);
    110.         $this->_routers = FLEA::getAppInf('routers');
    111.         $routerLoaded = true;
    112.     }
    113.     /**
    114.      * 根据服务器环境不同,取得RequestUri信息
    115.      *
    116.      * @return unknown
    117.      */
    118.     function getRequestUri() {
    119.      if ($this->_requestUri) return $this->_requestUri;
    120.         if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch
    121.             $requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
    122.         } elseif (isset($_SERVER['REQUEST_URI'])) {
    123.             $requestUri = $_SERVER['REQUEST_URI'];
    124.         } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI
    125.             $requestUri = $_SERVER['ORIG_PATH_INFO'];
    126.             if (!empty($_SERVER['QUERY_STRING'])) {
    127.                 $requestUri .= '?' . $_SERVER['QUERY_STRING'];
    128.             }
    129.         } else {
    130.          $requestUri = null;
    131.         }
    132.         $this->_requestUri = $requestUri;
    133.         return $requestUri;
    134.     }
    135.     function getBaseUrl() {
    136.      if ($this->_baseUrl) return $this->_baseUrl;
    137.         $filename = basename($_SERVER['SCRIPT_FILENAME']);
    138.         if (basename($_SERVER['SCRIPT_NAME']) === $filename) {
    139.             $baseUrl = $_SERVER['SCRIPT_NAME'];
    140.         } elseif (basename($_SERVER['PHP_SELF']) === $filename) {
    141.             $baseUrl = $_SERVER['PHP_SELF'];
    142.         } elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $filename) {
    143.             $baseUrl = $_SERVER['ORIG_SCRIPT_NAME']; // 1and1 shared hosting compatibility
    144.         } else {
    145.             // Backtrack up the script_filename to find the portion matching
    146.             // php_self
    147.             $path    = $_SERVER['PHP_SELF'];
    148.             $segs    = explode('/', trim($_SERVER['SCRIPT_FILENAME'], '/'));
    149.             $segs    = array_reverse($segs);
    150.             $index   = 0;
    151.             $last    = count($segs);
    152.             $baseUrl = '';
    153.             do {
    154.                 $seg     = $segs[$index];
    155.                 $baseUrl = '/' . $seg . $baseUrl;
    156.                 ++$index;
    157.             } while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos));
    158.         }
    159.         // Does the baseUrl have anything in common with the request_uri?
    160.         $requestUri = $this->getRequestUri();
    161.         if (0 === strpos($requestUri, $baseUrl)) {
    162.             // full $baseUrl matches
    163.             $this->_baseUrl = $baseUrl;
    164.             return $this->_baseUrl;
    165.         }
    166.         if (0 === strpos($requestUri, dirname($baseUrl))) {
    167.             // directory portion of $baseUrl matches
    168.             $baseUrl = rtrim(dirname($baseUrl), '/');
    169.             $this->_baseUrl = $baseUrl;
    170.             return $this->_baseUrl;
    171.         }
    172.         if (!strpos($requestUri, basename($baseUrl))) {
    173.             // no match whatsoever; set it blank
    174.             $this->_baseUrl = '';
    175.             return $this->_baseUrl;
    176.         }
    177.         // If using mod_rewrite or ISAPI_Rewrite strip the script filename
    178.         // out of baseUrl. $pos !== 0 makes sure it is not matching a value
    179.         // from PATH_INFO or QUERY_STRING
    180.         if ((strlen($requestUri) >= strlen($baseUrl))
    181.             && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0)))
    182.         {
    183.             $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
    184.         }
    185.        $baseUrl = rtrim($baseUrl, '/'); 
    186.        $this->_baseUrl = $baseUrl; 
    187.        return $this->_baseUrl;    
    188.     }
    189.     function getPathInfo () {
    190.         $baseUrl = $this->getBaseUrl();
    191.         if (null === ($requestUri = $this->getRequestUri())) {
    192.             return null;
    193.         }
    194.         // Remove the query string from REQUEST_URI
    195.         if ($pos = strpos($requestUri, '?')) {
    196.             $requestUri = substr($requestUri, 0, $pos);
    197.         }
    198.         if ((null !== $baseUrl)
    199.             && (false === ($pathInfo = substr($requestUri, strlen($baseUrl)))))
    200.         {
    201.             // If substr() returns false then PATH_INFO is set to an empty string
    202.             $pathInfo = '';
    203.         } elseif (null === $baseUrl) {
    204.             $pathInfo = $requestUri;
    205.         }
    206.         $this->_pathInfo = $pathInfo;
    207.         return $pathInfo;
    208.     }
    209.     
    210.     /**
    211.      * Matches a user submitted path with a previously defined route.
    212.      * Assigns and returns an array of defaults on a successful match.
    213.      *
    214.      * @param string Path used to match against this routing map
    215.      * @return array|false An array of assigned values or a false on a mismatch
    216.      */
    217.     function match($regex, $path, $defaults, $map)
    218.     {
    219.         $path = trim(urldecode($path), '/');
    220.         $res = preg_match($regex, $path, $values);
    221.         if ($res === 0) return false;
    222.         foreach ($values as $i => $value) {
    223.             if (!is_int($i) || $i === 0) {
    224.                 unset($values[$i]);
    225.             }
    226.         }
    227.         $values = $this->_getMappedValues($map, $values);
    228.         $defaults = $this->_getMappedValues($map, $defaults, false, true);
    229.         $return = $values + $defaults;
    230.         return $return;
    231.     }
    232.     /**
    233.      * Maps numerically indexed array values to it's associative mapped counterpart.
    234.      * Or vice versa. Uses user provided map array which consists of index => name
    235.      * parameter mapping. If map is not found, it returns original array.
    236.      *
    237.      * Method strips destination type of keys form source array. Ie. if source array is
    238.      * indexed numerically then every associative key will be stripped. Vice versa if reversed
    239.      * is set to true.
    240.      *
    241.      * @param array Indexed or associative array of values to map
    242.      * @param boolean False means translation of index to association. True means reverse.
    243.      * @param boolean Should wrong type of keys be preserved or stripped.
    244.      * @return array An array of mapped values
    245.      */
    246.     function _getMappedValues($map, $values, $reversed = false, $preserve = false)
    247.     {
    248.         if (count($map) == 0) {
    249.             return $values;
    250.         }
    251.         $return = array();
    252.         foreach ($values as $key => $value) {
    253.             if (is_int($key) && !$reversed) {
    254.                 if (array_key_exists($key, $map)) {
    255.                     $index = $map[$key];
    256.                 } elseif (false === ($index = array_search($key, $map))) {
    257.                     $index = $key;
    258.                 }
    259.                 $return[$index] = $values[$key];
    260.             } elseif ($reversed) {
    261.                 $index = (!is_int($key)) ? array_search($key, $map, true) : $key;
    262.                 if (false !== $index) {
    263.                     $return[$index] = $values[$key];
    264.                 }
    265.             } elseif ($preserve) {
    266.                 $return[$key] = $value;
    267.             }
    268.         }
    269.         return $return;
    270.     }
    271.     /**
    272.      * Assembles a URL path defined by this route
    273.      *
    274.      * @param array An array of name (or index) and value pairs used as parameters
    275.      * @return string Route path with user submitted parameters
    276.      */
    277.     function assemble($defaults, $map = array(), $reverse, $data = array())
    278.     {
    279.         if ($reverse === null) {
    280.             return '构建网址失败!路由参数错误!';   
    281.         }     
    282.         $data = $this->_getMappedValues($map, $data, true, false);
    283.         $data += $this->_getMappedValues($map, $defaults, true, false);
    284.         //$data += $this->_values;
    285.         ksort($data);
    286.         $return = @vsprintf($reverse, $data);
    287.         if ($return === false) {
    288.             return '构建网址失败!';  
    289.         }
    290.         return $return;
    291.     }
    292.     /**
    293.      * 使用路由构建网址
    294.      */
    295.     function url($routerName, $urlOptions, $absolute) {
    296.      $this->loadRouters();
    297.      if (isset($this->_routers[$routerName])) $curRouter = $this->_routers[$routerName];
    298.      elseif (isset($this->_curRouter)) $curRouter = $this->_curRouter;
    299.   if (is_array($curRouter) && count($curRouter) == 4 && is_string($curRouter[3])) {
    300.    $defaults = $curRouter[1];
    301.    $map = $curRouter[2];
    302.    $reverse = $curRouter[3];
    303.   } else {
    304.    return '构建网址失败!路由参数错误!';
    305.   }
    306.      if (is_array($map) && is_string($reverse))
    307.       if (!$absolute) return $this->assemble($defaults, $map, $reverse, $urlOptions);
    308.       else {
    309.        if (!$this->_baseUrl) $this->getBaseUrl();
    310.        return $this->_baseUrl . '/' .$this->assemble($defaults, $map, $reverse, $urlOptions);
    311.       }
    312.     }
    313. }
    复制代码
    这里要说一个比较好的自定义类的命名规则及文件放置位置。
    在FLEA下面建一个My的目录里面放自已的类。比如My_Dispatcher_Regexp放在:
    My/Dispatcher/Regexp.php

    同时为方便写一个生成网址助手:
    My_Helper_Router
    My/Helper/Router.php
    代码如下:
    1. <?php
    2. /**
    3. * 路由网址助手
    4. */
    5. function rurl($routerName, $urlOptions, $absolute = false) {
    6. $routerHelper =& FLEA::getSingleton('My_Dispatcher_Regexp');
    7. echo $routerHelper->url($routerName, $urlOptions, $absolute);
    8. }
    复制代码
    使用方法:
    /* 修改默认的Dispatcher为自定义的Dispatcher类*/
    FLEA::setAppInf('dispatcher','My_Dispatcher_Regexp');

    /* 设置路由配置信息的文件位置*/
    FLEA::setAppInf('routerConfig', './APP/config/router.php');

    其它代码跟任何一个普通的例子一样。

    controller里面代码如下:
    1. <?php
    2. class Controller_Default extends FLEA_Controller_Action
    3. {
    4. function actionIndex()
    5. {
    6. FLEA::loadFile('My_Helper_Router');
    7. include('APP/View/PostIndex.php');
    8. }
    9. }
    复制代码
    我们在view中用下面代码:
    1. <?php
    2. dump($_GET);
    3. rurl('myFirstRouter', array('id' => '33', 'name' => 'thename'));
    复制代码
    就可以看到$_GET得到正确的参数,
    rurl也生成我们期望的网址:
    blog/view/33-thename.html

    绝对网址生成方法如下:
    1. rurl('myFirstRouter', array('id' => '33', 'name' => 'thename'),true);
    2. //将生成如下的网址:
    3. /other/fleaphp/test/blog/view/33-thename.html
    4. 如果没有使用apache的mod_rewrite功能生成的网址如下:
    5. /fleaphp/test/index.php/blog/view/33-thename.html
  • 相关阅读:
    8月10日
    8月9日
    8月8日
    8月7日
    8月6日
    8月5日
    《大道至简》读后感
    8月4日
    8月3日
    8月2日
  • 原文地址:https://www.cnblogs.com/firstdream/p/2389338.html
Copyright © 2011-2022 走看看