【问题标题】:Django-like URL Routing for PHPPHP 的类似 Django 的 URL 路由
【发布时间】:2011-06-24 08:44:07
【问题描述】:

我正在寻找一种方法来提供类似于 Django 中的 URL 路由。我在网上查看了很多资源,我喜欢cobweb,但问题是我不想使用整个框架,我只想使用 URL 重新路由逻辑/代码。对于类似 Django 的 URL 路由逻辑是否有很好的资源?

【问题讨论】:

    标签: php django url-rewriting url-routing


    【解决方案1】:

    您可以查看CakePHP。我不知道将 URL 路由逻辑从框架的其余部分中提取出来是多么容易。

    【讨论】:

      【解决方案2】:

      我不认为是完全相同的,但是 Zend 框架具有您可能想要查看的非常好的下降路由功能。 Zend 框架是一种基于组件的框架,它不会强迫您使用整个框架。但我认为,如果您使用路由功能,您可能还需要使用它们的控制器机制,因为路由器是建立在顶部的。

      【讨论】:

      • 嗯,好的。我希望避免使用控制器。
      【解决方案3】:

      您正在寻找的是一个微框架。它基本上只是框架的路由层。其中有几种可用。这些对我来说很有趣:

      真正让我大吃一惊的是Silex,它基于 Symfony2,需要 PHP 5.3。

      【讨论】:

      • 感谢您的建议。我会检查所有选项。
      • 我刚刚添加了一个注释,Silex 不稳定,必须澄清。
      【解决方案4】:

      我看过 Limonade 微型 PHP 框架的 URL 路由发布了一个使用 limonade 代码库的回复。但是我回去查看了蜘蛛网代码,它有点漂亮和漂亮。所以我只是采用了 Cobweb 的 URL 路由并在 OOP PHP5.x 中对其进行了重构,以便在我自己的代码中使用。

      比较参见:- http://docs.djangoproject.com/en/dev/topics/http/urls/ vs. http://www.limonade-php.net/README.htm

      通常的免责声明已经到位

      1) 我没有测试太多!

      2) 它可能不具备 Django 的所有 URL 路由功能

      <?php
      
      /**
       *
       * @author rajeev jha (jha dot rajeev at gmail)
       * Django style URL routing. 
       * Pattern matching logic of this code is copied from cobweb framework
       * @see http://code.google.com/p/cobweb/source/browse/trunk/dispatch/url_resolver.class.php 
       *  
       */
      
      class Gloo_Core_Router {
      
        private $table ;
      
      
          function __construct() {
          //initialize routing table 
          $this->table = new Gloo_Core_RoutingTable();
          }
      
        function getRoute($path,$domain=NULL){
      
          if(empty($path)) {
            $message = sprintf("Please supply a valid path to match :: got [%s] ", $path);
            trigger_error($message,E_USER_ERROR);
          }
      
          //all rules for this domain 
          $rules = $this->table->getRules($domain);    
          $route = NULL ;
      
          if($path == '/') 
            $route = $this->matchHome($rules);  
          else 
            $route = $this->match($rules,$path);
      
          return $route ;
      
        }
      
        private function matchHome($rules) {
          $route = NULL ;
      
          foreach($rules as $rule) {
            if($rule["pattern"] == '/') {
              $route = $this->createRoute($rule,array());
            }
          }
      
          return $route ;
      
        }
      
        private function match($rules,$path) {
          $path = ltrim($path, '/');
          $matches = array();
          $route = NULL ;
      
          foreach($rules as $rule) {
            if(preg_match($this->patternize($rule["pattern"]),$path,$matches) != 0 ) {
              //match happened 
              $matches = $this->sanitizeMatches($matches);
              $route = $this->createRoute($rule,$matches);
            }
          }
      
          return $route ;
      
        }
      
        private function createRoute($rule,$matches) {
      
          $route = $rule ;
          //add parameters
          $route["params"] = $matches ;
          return $route ;
        }
      
        private function sanitizeMatches($matches){
          //discard the first one 
          if (count($matches) >= 1)
            $matches = array_splice($matches,1);  
      
          $unset_next = false;
      
          //group name match will create a string key as well as int key 
          // like match["token"] = soemthing and match[1] = something 
          // remove int key when string key is present for same value
      
          foreach ($matches as $key => $value) {
            if (is_string($key)){
              $unset_next = true;
            } else if (is_int($key) && $unset_next) {
              unset($matches[$key]);
              $unset_next = false;
            }
          }
      
          return array_merge($matches);
      
        }
      
        private function patternize($pattern) {
          //http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php
          //treat pattern as UTF-8
          return '{'.$pattern.'}u' ;
        }
      
      }
      
      ?>
      
      
      <?php
      
      /**
       *
       * @author rajeev jha (jha dot rajeev at gmail)
       * Django style URL routing. 
       * URL routing table 
       *  
       */
      
      
      class Gloo_Core_RoutingTable {
      
        private $rules ;
        private $splrules ;
        const ANY_DOMAIN = '__ANY__' ;
      
      
        function __construct() {
          $this->rules = array();
          $this->splrules = array();
      
          //@todo inject from outside    
          $this->createRule(self::ANY_DOMAIN, '/', 'Gloo_Controller_Home');
          //match alphanumeric + dashes
          //a pcre word (\w) does not contain dashes
          $this->createRule(self::ANY_DOMAIN, '^(?P<token>[-\w]+)$','Gloo_Controller_Post');
          $this->createRule(self::ANY_DOMAIN,  '^page/(?P<pagenum>\d+)$','Gloo_Controller_Home');
          $this->createRule(self::ANY_DOMAIN,  '^(?P<token>\w+)/page/(?P<pagenum>\d+)$','Gloo_Controller_Post');
          $this->createRule(self::ANY_DOMAIN, '^category/(?P<name>\w+)$','Gloo_Controller_Category');
          $this->createRule(self::ANY_DOMAIN,  '^category/(?P<name>\w+)/page/(?P<pagenum>\d+)$','Gloo_Controller_Category');
      
          //special rules 
          $this->createRule('www.test1.com','^(?P<token>\w+)$','Gloo_Controller_File', array("template" => "post.php"));
      
        }
      
        function createRule($domain,$pattern,$action,$options=NULL) {
      
          if(empty($domain)) {
            trigger_error("No domain supplied for rule" ,E_USER_ERROR);
          }
      
      
              $rule = array();
      
          $rule["pattern"] = $pattern;
          $rule["action"] = $action ;
      
              //Add options
      
          if(is_null($options))
            $rule["options"] = array();
          else
            $rule["options"] = $options ;
      
          $rule["domain"] = $domain ;
      
          //add to generic or domain specific rules
          if($domain == self::ANY_DOMAIN)
            $this->rules[] = $rule ;
          else
            $this->splrules[$domain][] = $rule ;
      
        }
      
        function getRules($domain) {
          if(empty($domain))
            return $this->rules ;
      
          //valid domain - rules as well
          // add to existing rules
      
          if(array_key_exists($domain,$this->splrules)) {
            $splrules = $this->splrules[$domain];
            $rules = array_merge($this->rules,$splrules);
            return $rules ;
      
          } else {
            return $this->rules ;
          }
      
        }
      
      }
      
      
      ?>
      

      现在,您可以向路由表初始化添加任何规则。根据您提供给路由器的域+“路径”,您将获得“控制器”字符串以及“命名组”参数和其他匹配的参数。我不包括“控制器”字符串的类实例化逻辑,因为 1)那会很复杂 2) 如果您的目的只是获得类似 Django 的 URL 路由,那么这已经足够了。

      参考文献

      1. 柠檬水代码在这里:- https://github.com/sofadesign/limonade/blob/master/lib/limonade.php

      2. 蜘蛛网代码在这里:- http://code.google.com/p/cobweb/source/browse/trunk/dispatch/url_resolver.class.php

      3. 我的代码在这里:- https://code.google.com/p/webgloo/source/browse/trunk/php/lib/Gloo/Core/Router.php
      4. 我的代码的旧版本:- 我在此处编辑的内容 - 基于柠檬水,并且严重损坏了大脑。随意查看上面的 Limonade 链接。我正在删除它。

      用法

      $router = new Gloo_Core_Router();

      $path = 'category/news/page/3' ;
      printf("Now matching path [%s]" , $path);
      $route = $router->getRoute($path);
      print_r($route);
      
      $path = '/category/Health/page' ;
      printf("Now matching path [%s]" , $path);
      $route = $router->getRoute($path);
      print_r($route);
      

      您必须更改类名并包含依赖项,但是嘿,您是程序员;D

      【讨论】:

        【解决方案5】:

        我用 codeigniter 和 django 资源开发了一个类似的框架,http://williamborba.github.io/willer/quick_start/

        目前还是测试版,不过我正在逐步实现和改进 URL.php 文件与 URLS.py django 非常相似。

        另一个亮点是模型和 ORM,很像 django,但与 codeigniter 活动记录类似。

        【讨论】:

          猜你喜欢
          • 2011-09-11
          • 2011-07-02
          • 1970-01-01
          • 2019-01-14
          • 2011-08-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多