澳门新葡萄京官网首页 14

制作类似ThinkPHP框架中的PATHINFO模式功能

这是一篇介绍如何用php来实现MVC模式开发的文件。关于MVC模式的技术文章网上随处可以,所以这篇文件将不再讲述这种模式的优缺点,子讲他的php技术实现。并且在以后的系列文章中也是以讲技术为主。一、实现统一的网站入口大家也许经常在网上看到这样的路径(),让人不解,这样的网站的实现方式有几种可能性:1、隐藏文件的扩展名,对这种做法的好处,众说纷纭,不过个人觉得没有必要;2、用了网站的重定向规则,实现虚拟路径;3、强制文件解析的方式,实现虚拟路径。用第23种方法可以实现网站的统一接口,合理的整合网站,更好的体现网站的安全性和架构,用这两种方式的网站大多是使用MVC模式构建和实现的。下面是一个例子访问路径如下:
……/test/*******/Bad……/test/*******/Good(其中的******可以用任何字符串替换,…….是你的web路径)
文件的目录结构如下
|–.htaccess|–test|–Application.php|–Controler/GoodControler.php|–Controler/BadControler.php注意文件.htaccess,在windows下不能直接建立的,可以在命令行模式下建立.
文件0:(.htaccess)(这个文件是更改apache的配置方式用的)
filestestforcetypeapplication/x- 文件1:(test.php)
?php/*————————————-*test.php**作为你的网站的入口的文件*用来初始化和入口*调用执行Controler的调用*————————————-*/requireApplication.php;$aa=newApplication();$aa-parse();$aa-go();?
文件2:(GoodControler.php) ?

澳门新葡萄京官网首页 1

  下半部分是方法getRoute,是用来匹配处理访问路径的。即将访问的路径传进来,再与$routes里面的正则表达式进行匹配,成功后再进一步处理,返回处理结果。

可以看看上面的文件目录来理解下面的各个文件。

 1 <?php
 2 include './Framework/Core/Core.php';
 3 
 4 $router=new Url();
 5 $router->addRoute("/alpha:module/alpha:controller/[0-9]+?:a1a");
 6 $router->addRoute("/alpha:module/alpha:controller/alpha:action"); 
 7 $router->addRoute("/alpha:module/alpha:controller/alpha:action/(www[0-9]+?):id");
 8 
 9 $url=$_SERVER['REQUEST_URI'];
10 $urls=$router->getRoute($url); 
11 $_GET['urls']=$urls;
12 $m=$urls['module'];
13 $c=$urls['controller'];
14 $a=$urls['action'];
15 if($m&&$c)
16 {
17     $autoload=new Autoload($m,$c);
18     $autoload->PutFile();
19 }
20 $object=new $c;
21 $object->$a();
22 
23 ?>

  1、输出一

代码功能解析:

  1、很明显,输出的类属性$routes里面存贮的是正则表达式。

  preg_matches()在PHP5.2.2是新增了一个小语法,在这里小语法很关键。

下一次打算将它改成存储式的,将addRoute的存入在$routes的正则路径存贮在文件中,getRoute用的时候再取出来。再用apache的ab进行压力测试。

开始访问:

四、环境说明

下面要是简单介绍自动载入类文件,生成对象,并调用方法。

      (正则表达式)代表采用自己所写的表达式=》例如:(www[0-9]+?)

  这里的作用就是将所有访问www.test2.com的路径都只能index.php路径进入,即为单一入口。

  才刚开始搭建的,目录很简陋,还未完善哈,毕竟还是菜鸟级别,大神们勿喷,可以的话请,还请各位指点指点哈。

特别注意:

  三、四输出是用来查看理解preg_match()函数用的

测试完毕需要将Url.class.php文件恢复原样

   
  alphanum代表self::REGEX_ALPHANUMBERIC=》([0-9a-zA-Z_-]+?)

  放松放松,来个小小的过渡,哈哈。由于最近打算搭建一个mini型的超级超级小的框架(此处犯了意思相同的语法错误,得零分,哈哈),加强与巩固一下自己基础知识。以MVC模式进行搭建,所以就少不接触模型呀控制器呀行为之类的了。之前一直用ThinkPHP,感觉ThinkPHP中的URL中的默认模式PATHINFO很强大。所以就决定制作一个这样的功能用于自己的小框架的URL上啦。之前一直想去研究一下ThinkPHP的原码,由于没有时间,到现在都还没有去实施。打算在这个寒假里好好研究一下这个框架的原码,大学生涯最后一个寒假啦。

注意:

我的目标路径是这样子的(当然TP也可以很轻松做到这样子):

  4、switch中,就是匹配选择正则表达式,可以是已经定义好的,也可以是自己所写。例如:

小结:

  当多个路径时,将会全部保存在$routes中

1 <IfModule mod_rewrite.c>
2    RewriteEngine on
3    RewriteCond %{Request_FILENAME} !-f
4    RewriteRule !.(js|ico|gif|jpg|png|css)$ /index.php
5 </IfModule>

 

/Framework/Core/Autoload.class.php

澳门新葡萄京官网首页, 

澳门新葡萄京官网首页 2

  采用apache的rewrite模块,将所有访问这个站点的路径都只能从单一index.php入口进入。(由于apache重写规则也是一块硬骨头,在这里就不展开来细讲啦,到时候再另外写一篇文章来总结这个重写规则,与大家一起相互学习学习。作者博客:)

  在MVC模式中最基础且需要处理的就是M、C、A三个参数,这三个参数思想贯穿于整个模式代码中。在这里我们需要处理的就是URL,即是我们只需要通过路径的module、controller、action就能够确定所访问的哪个类哪个控制器以及行为。对于这些类的对象object生成以及行为方法的调用都是自动的,不需要我们另外再去编写代码一一处理。因此对于如何精准将类文件载入以及调用方法是个很关键的步骤。PHP中内部自带有一个new
Object时自动触发的函数,那就是__autoload(),它扩展函数spl_autoload_register()注册自动加载函数。

  preg_matches()第一参数为正则表达式,此处我们将$routes中的放入进去。

3、主要代码

  3、输出三与四

  这里主要是展示一下我的文件夹,方便下面的理解分析。这个功能重点是Url.class.php文件。

      int代表self::REGEX_INT即正则表达为=》([0-9]+?)

开始访问:

澳门新葡萄京官网首页 3

结果与小结:

声明:本博客文章为原创,只代表本人在工作学习中某一时间内总结的观点或结论。转载时请在文章页面明显位置给出原文链接。

到这里整个Url.class.php类文件讲解分析完毕,接下来就是MVC的访问啦。

  foreach匹配时,假若$routes含有多个正则表示式时,它将会按顺序一个一个表达式的与URL匹配,若都匹配成功,那么后面的将会覆盖前面的值。

然而在这篇文章中我所要讲述的就是如何搭建好这种友好的访问路径。

  2、私有方法_ParseRoute中,调用了_normalize()方法处理$key,这个方法就是将$key除a-zA-Z0-9以外的符号过滤掉。

  2、输出二

五、代码实例

       alpha代表self::REGEX_ALPHA即正则表达式=》([a-zA-Z_-]+?)

 1 <?php
 2 header("content-type:text/html;charset=utf8");
 3 include "./Framework/Core/Url.class.php";   #载入类文件
 4 $router=new Url();
 5 #添加规则
 6 $router->addRoute("/alpha:module/alpha:controller/[0-9]+?:a1a");
 7 $router->addRoute("/alpha:module/alpha:controller/alpha:action"); 
 8 $router->addRoute("/alpha:module/alpha:controller/alpha:action/(www[0-9]+?):id");
 9 $url=$_SERVER['REQUEST_URI'];
10 echo "<pre>";
11 echo "index.php第一个输出<br/>";
12 print_r($url);
13 echo "</pre>";
14 $urls=$router->getRoute($url); 
15 echo "<pre>";
16 echo "index.php getRoute输出结果 第五个输出<br/>";
17 print_r($urls);
18 echo "</pre>";die;
19 ?>

2、正则表达式

 

index.php文件

测试二:

index.php代码如下

2、开启apache的rewrite模块

澳门新葡萄京官网首页 4

澳门新葡萄京官网首页 5

1 <?php
2 include "./Framework/Core/Url.class.php";   #载入类文件
3 $router=new Url();
4 #添加规则
5 $router->addRoute("/alpha:module/alpha:controller/alpha:action"); 
6 ?>

再在Url.class.php的addRoute方法中添加一个输出,用来观察,如下图:

  上半部分是方法addRoute,是用来添加路径正则表达式的,并将其存贮在类属性$routes里。

澳门新葡萄京官网首页 6

两者相比较很容易就得出结论:PathInfo模式下的访问路径显示更加友好!

三、所涉及的核心知识

  假若使用了这个小语法(?P<name>),假若这个子组匹配了的话,那么它会将匹配的数据与这个name参数形成一对关联元素,存贮于preg_matches()的第三参数数组中。这就很好的解释上述addRoute()的参数冒号后的值为何用了,以及澳门新葡萄京官网首页 7的用法。

大功告成,码字码到手都累啦。这里URL路径是没有处理大小写的,所以module、controller、action都是对大小写敏感的。

  搞PHP的都知道ThinkPHP是一个免费开源的轻量级PHP框架,虽说轻量但它的功能却很强大。这也是我接触学习的第一个框架。TP框架中的URL默认模式即是PathInfo模式。这个模式很强大,每当你访问一个网站必然带有一长串参数,但是太长又显得不太友好。对于访问一个以MVC模式搭建的网站,必然带有M、C、A三个参数即module、controller、action,这些参数需要还需要用&符号隔开,假若参数量很多,就显得特别的不友好啦。然而PathInfo模式功能就是将这一长串缩短简化,让这个路径变得更加友好的显示。

传统的访问路径是这样子的:

Url.class.php

  第三个输出,如下图

以上三个路径所表示的意思是一样的即都访问同一个站点,带有同样的参数

澳门新葡萄京官网首页 8

澳门新葡萄京官网首页 9

  1 <?php
  2 /*
  3 *@作 者 :壹叶随风
  4 *@博 客 :http://www.cnblogs.com/phpstudy2015-6/
  5 *@时 间 :2017.1.3
  6 */
  7 class Url
  8 {
  9     //定义正则表达式常量
 10     const REGEX_ANY="([^/]+?)";                   #非/开头任意个任意字符
 11     const REGEx_INT="([0-9]+?)";                  #数字
 12     const REGEX_ALPHA="([a-zA-Z_-]+?)";           #字母
 13     const REGEX_ALPHANUMERIC="([0-9a-zA-Z_-]+?)"; #任意个字母数字_-
 14     const REGEX_STATIC="%s";                      #占位符
 15     const ANY="(/[^/]+?)*";                       #任意个非/开头字符
 16 
 17     protected $routes=array(); #保存路径正则表达式
 18 
 19     #添加路由正则表达式
 20     public function addRoute($route)
 21     {
 22         $this->routes[]=$this->_ParseRoute($route);
 23     }
 24 
 25     /*private
 26       @input :$route 输入路由规则
 27       @output:return 返回路由正则规则
 28     */
 29     private function _ParseRoute($route)
 30     {
 31         $parts=explode("/", $route);  #分解路由规则
 32         $regex="@^";  #开始拼接正则路由规则
 33         if(!$parts[0])
 34         {
 35             array_shift($parts);  #除去第一个空元素
 36         }
 37         foreach ($parts as $part) 
 38         {
 39             $regex.="/";
 40             $args=explode(":",$part);
 41             if(!sizeof($args)==2)
 42             {
 43                 continue;
 44             }
 45             $type=array_shift($args);
 46             $key=array_shift($args);
 47             $this->_normalize($key);  #使参数标准化,排除其他非法符号
 48             $regex.='(?P<'.$key.'>';    #为了后面preg_match正则匹配做铺垫
 49             switch (strtolower($type)) 
 50             {
 51                 case 'int':      #纯数字
 52                     $regex.=self::REGEX_INT;
 53                     break;
 54                 case 'alpha':    #纯字母
 55                     $regex.=self::REGEX_ALPHA;
 56                     break;
 57                 case 'alphanum':  #字母数字
 58                     $regex.=self::REGEX_ALPHANUMBERIC;
 59                     break;
 60                 default:
 61                     $regex.=$type; #自定义正则表达式
 62                     break;
 63             }
 64             $regex.=")";
 65         }
 66         $regex.=self::ANY;   #其他URL参数
 67         $regex.='$@u';
 68         return $regex;
 69     }
 70 
 71     /*public,将输入的URL与定义正则表达式进行匹配
 72       @input  :$request 输入进来的URL
 73       @output :return 成功则输出规则数组数据 失败输出false
 74     */
 75     public function getRoute($request)
 76     {
 77         #处理request,进行参数处理,不足M、C、A,则自动补为home、index、index,即构建MVC结构URL
 78         $request=rtrim($request,'/');           #除去右边多余的斜杠/
 79         $arguments=explode('/',$request);
 80         $arguments=array_filter($arguments);    #除去数组中的空元素
 81         $long=sizeof($arguments);               #数组中的个数
 82         switch ($long)                          #判断个数,不足就补够
 83         {
 84             case '0':
 85                 $request='/home/index/index';
 86                 break;
 87             case '1':
 88                 $request.='/index/index';
 89                 break;
 90             case '2':
 91                 $request.='/index';
 92                 break;
 93         }       
 94         $matches=array();                       #定义匹配后存贮的数组
 95         $temp=array();                          #中间缓存数组
 96         
 97         foreach ($this->routes as $v)           #开始匹配
 98         {
 99             preg_match($v, $request, $temp);    #需要重点理解这个数组
100             $temp?$matches=$temp:'';
101         }
102         if($matches)                            #判断$matches是否有数据,无返回false
103         {
104             foreach ($matches as $key => $value) #筛选
105             {
106                 if(is_int($key))
107                 {
108                     unset($matches[$key]);      #除去数字key元素,保留关联元素。与上面的preg_match一起理解
109                 }
110             }
111             $result=$matches;
112             if($long > sizeof($result))         #URL参数超过后的处理
113             {
114                 $i=1;
115                 foreach ($arguments as $k => $v) 
116                 {                      
117                     if($k > sizeof($result))
118                     {
119                         if($i==1)
120                         {
121                             $result[$v]='';
122                             $temp=$v;
123                             $i=2;
124                         }
125                         else
126                         {
127                             $result[$temp]=$v;
128                             $i=1;
129                         }                           
130                     }
131                 }
132             }
133             return $result;
134         }
135         return false;
136     }
137     #使参数标准化,不能存在符号,只能是a-zA-Z0-9组合
138     private function _normalize(&$param)
139     {
140         $param=preg_replace("/[^a-zA-Z0-9]/", '', $param);
141     }
142 }
143 /*使用实例:
144 include './Url.class.php';
145 $router=new Url();
146 $router->addRoute("/alpha:module/alpha:controller/[0-9]+?:a1a");
147 $router->addRoute("/alpha:module/alpha:controller/alpha:action"); 
148 $router->addRoute("/alpha:module/alpha:controller/alpha:action/(www[0-9]+?):id"); 
149 $url=$_SERVER['REQUEST_URI'];
150 $urls=$router->getRoute($url); 
151 echo "<pre>";
152 print_r($urls);
153 echo "</pre>";
154 */
155 ?>

  针对上面的Url.class.php类文件,我们可以在根目录建立一个test.php测试文件或者直接在index.php文件上测试(方便快捷),帮助我们进一步了解这个类文件的原理与功能。(这里我就不建立test文件啦,直接在index.php文件上进行测试啦)

 1 <?php
 2 #用于加载控制器文件
 3 class Autoload
 4 {
 5     private $path='';
 6     public function __construct($module,$controller)
 7     {
 8         $this->path=__DIR__."/../../Application/".$module."/Controller/".$controller."Controller.class.php";
 9     }
10     public function PutFile()
11     {
12         if(is_file($this->path)) #判断文件是否存在
13         {
14             require_once($this->path);
15         } 
16         else
17         {
18             return false;
19         }
20     }
21 }
22 
23 ?>

/Framework/Function/AutoLoad.function.php

测试一:

  preg_matches()第二参数为不必要参数,填了此参数,则将匹配成功的值全部放入这个数组中。

  简单解析:1、RewriteEngine on
开启重写 2、RewriteRule
重写规则,表示非上述后缀的路径都适合  3、RewriteCond
 判断是不是文件

澳门新葡萄京官网首页 10

…..

多一点思考、多一点琢磨、多一点敲代码,争取早日迈入大神行列!

…..

-为学须刚与恒,不刚则隋隳,不恒则退

 1 <?php
 2 #用于加载核心文件
 3 spl_autoload_register('CoreFunction');
 4 function CoreFunction($classname)
 5 {
 6     $file=__DIR__."/../Core/".$classname.".class.php";
 7     if(is_file($file))
 8     {
 9         require_once($file);
10     }    
11 }
12 ?>

开始访问:

与大家共勉吧,坚持就是success嘛!好啦扯远啦,言归正传,我所制作的PATHINFO功能上和ThinkPHP是一致的,至于里面的深层原理效率问题什么的,是否和TP中的PATHINFO一样就不太清楚啦,毕竟还没有去研究TP原码,这里就按照我自己的思路来写。

  5、$regex.=self::ANY;
这里的作用是用来匹配URL路劲其他参数用的,即

  在相应的配置文件将其打开就好,这里就不讲解了。

  第二个输出,用来查看多个正则表达式时$routes的值,如下图:

2、

  正则表达式的基本知识、PHP中的preg_match()函数,这个函数是制作这个功能的关键,所以需要重点理解。

还有两个模块里面的控制器文件

结果为:

  3、正则表达式中,【P<‘.$key.’>】,是用来后面的preg_match匹配用的,后面讲解。

再在Url.class.php的getRoute方法中添加以下输出:

/Framework/Core/Core.php

  上面这个Url.class.php类文件代码大概可以分为两部分,在75行即方法getRoute那个地方可以将其分为上半部分和下半部分。

  接着在根目录建立.htaccess文件,这里主要是放重写规则,如下所示:

index.php代码更改如下:

澳门新葡萄京官网首页 11

  当使用 PCRE
函数的时候,模式需要由分隔符闭合包裹。分隔符可以使任意非字母数字、非反斜线、非空白字符。如果分隔符经常在
模式内出现, 一个更好的选择就是是用其他分隔符来提高可读性。

  由此可以知道$routes中的值@的意思了,就是分隔符,只是我们经常用/而已。

而ThinkPHP在默认的URL模式下能够做到这样子的路径:

1、apache的rewrite模块。

  preg_matches()第二参数为需要匹配的数据,这里我们将传入进来的URL放进去(此处URL是输出一的值)。

  这里就是getRoute()方法处理URL返回的结果。

  澳门新葡萄京官网首页 12

  这个文件夹的话,随个人的想法来建立。要是用于框架上的话,这一步就显得很重要啦。具体可以参考各个框架的文件目录结构。我的文件目录如下图:

澳门新葡萄京官网首页 13

 1 <?php
 2 class Test
 3 {
 4     public $aa=2;
 5     public function action()
 6     {
 7         echo "admin---->test----->action";
 8         echo "<pre>";
 9         print_r($_GET);
10         echo "</pre>";
11     }
12 }
1 <?php
2 #核心文件
3 #载入PHP自动加载函数文件
4 include_once(__DIR__."/../Function/AutoLoad.function.php");
5 ?>

  对于路径的问题,由于需要实现自动化即自动载入类文件等等,所以需要相对健壮的载入路径代码,让其移植性强一点。例如在Window和Linux系统下能够畅通无阻,所以需要用到PHP中的一个魔术常量__DIR__来写路径代码。

结果:

测试一结束后,将Url.class.php类文件恢复原状!

(以上是自己的一些见解,若有不足或者错误的地方请各位指出)

结果为:

  这里需要重点讲解preg_matches()功能。

…..

我将此文件放入/Framework/Core文件夹中

澳门新葡萄京官网首页 14

1、建立好相应文件夹。虽然这个例子很简单但是我们也不能含糊过去,养成良好的习惯,争取早入成为大神,哈哈

  此处需要理解体会$_SERVER

Admin中的TestController.class.php

二、写作小背景

3、类文件的自动载入与路径问题

Home中的TestController.class.php

一、PATHINFO功能简述

1、

 1 <?php
 2 class Test
 3 {
 4     public $aa=2;
 5     public function action()
 6     {
 7         echo "home---->test----->action";
 8         echo "<pre>";
 9         print_r($_GET);
10         echo "</pre>";
11     }
12 }

  4、输出五

  因此添加正则路劲addRoute的参数形式:【/int:module/alpha:controller/alphanum:action/(www[0-9]+?):id】任意组合(无数个都可以),冒号后面的参数与preg_match共同使用,后面讲解。

作者:那一叶随风

  Linux虚拟机、PHP5.3.6、域名www.test2.com

  第四个输出,如下图

发表评论

电子邮件地址不会被公开。 必填项已用*标注