我们为什么要使用路由?原因1:一个更漂亮的URI

1.URI的改进

刚刚开始学PHP时,我们一定写过blog.php?id=1之类的URI,使用GET方式获取参数。这样的URI有两个缺点,一是容易被SQL注射攻击,二是维护性可读性差,大家可以比较下面两种URI哪一种更具备可读性。

www.mysite.com/blog.php?id=1

复制代码

上面URI是我们初学PHP最常用的。

www.mysite.com/blog/1

复制代码

这种URI是目前最流行的URI,举个例子,比如很多读书类,电影类网站,都使用了这样的URI,这样的URI要比index.php?a=1&b=2&c=3&d=4....要简洁很多。

2.实现方法

在WEB项目的根目录下写一个.htaccess文件

RewriteEngine On

RewriteRule ^([a-zA-Z0-9/]*)$ index.php/$1

复制代码

重写规则,让域名后面的字符串直接做为一个参数传入index.php,这样index.php就成为了你整个WEB应用的中心,定义了“请求和响应的映射”。

原因2:单一入口机制的易维护性

1.路由数组

一个PHP初学者,刚开始做项目,项目做着做着规模做大了,常常这个PHP页面给另一个PHP页面用GET方法传值,有时传的值还不止一个,时间一久,你的WEB项目,N个PHP页面宛如一个复杂的蜘蛛网,让你难以维护。一旦有修改,会涉及很多PHP文件,工作量很大。

MVC的单一入口机制可以解决维护难的问题,路由就是一套映射,可以让你一个URI对应一个方法。

$route=[

''=>'IndexController@Index',

'blog'=>'BlogController@Show',

'blog/{id}/{name}'=>'BlogController@Show',

];

复制代码

2.获取参数

$path=$_SERVER['PATH_INFO'];

$path=ltrim($path,'/');

echo $path.PHP_EOL;

复制代码

我们在浏览器里输入:www.mysite.com/blog/1后,path变量为/blog/1。使用ltrim函数删除左边的斜杠,然后使用explode把字符串拆解成数组。

$path_arr=explode('/', $path);

复制代码

核心代码如下:

if(isset($_SERVER['PATH_INFO'])){

$path=$_SERVER['PATH_INFO'];

$path=ltrim($path,'/');

$path_arr=explode('/', $path);

}

if(isset($path_arr[0])){

$key=$path_arr[0];

unset($path_arr[0]);

}

else{

$key='';

}

if(isset($path_arr[1])){

$parameters=array_values($path_arr);

}

if(isset($route[$key])){

$arr=explode('@', $route[$key]);

$controller=new $arr[0];

$action=$arr[1];

if(isset($parameters)){

$controller->$action($parameters);

}

else{

$controller->$action();

}

}

else{

require 'error.html.php';

}

复制代码

unset函数可以销毁数组中key和value,但是并不会重建索引,所以path_arr[0]是要调用的控制器类和方法名,path_arr[1]或者path_arr[1..N]就作为传入方法的参数。

重定向和错误页面是WEB系统中最常见的,如果不用路由机制,你可能要没完没了的重复写重定向或者错误页面的显示或者跳转代码,有了路由,只需要一句话就可以完成。

原因3:减少资源的消耗

MVC采用了控制器(controller)来响应请求(request),每次请求来时,应该在指定的一个PHP文件中初始化这个控制器,而不是分别在不同的PHP文件中做初始化工作,这样可以减少资源的消耗。

是不是一定要用控制器?方案1:不用控制器

我们现在路由数组里添加一项,value不是一个字符串,而是一个匿名函数(Closure)

$route=[

''=>'Index',

'blog'=>'BlogController@Show',

'blog/{id}/{name}'=>'BlogController@Show',

'f'=>function(){echo 'hello';}

];

复制代码

这里的route[f]是一个匿名函数,并不是一个控制器类的方法,所以,我们要把上一节路由代码做一下修改:

if(isset($route[$key])){

if($route[$key] instanceof Closure){

$route[$key]();

}

else{

$arr=explode('@', $route[$key]);

$controller=new $arr[0];

$action=$arr[1];

if(isset($parameters)){

$controller->$action($parameters);

}

else{

$controller->$action();

}

}

}

else{

require 'error.html.php';

}

复制代码

方案2:使用控制器

每一次都require一个html页面是一件很不优雅的事情,所以我们写一个render函数

function render($path,array $args){

extract($args);

require($path);

}

复制代码

接上一篇博客,我们知道每个URI对应了一个方法,但是我们常常遇到这样的问题:

class Controller{

public function __call($method,$args){

echo 'has not this function'.$method;

}

}

class IndexController extends Controller{

public function Index(){

echo __CLASS__;

for($i=1;$i<=20;++$i){

$data[$i]='content';

}

render('template.html.php',['data'=>$data]);

}

}

class BlogController extends Controller{

public function Show(){

echo __CLASS__;

for($i=1;$i<=10;++$i){

$data[$i]='blog';

}

render('template.html.php',['data'=>$data]);

}

}

?>

复制代码

用不用控制器,取决于你的业务复杂度。个人建议使用控制器,但是对于业务很简单的页面跳转或检查,可以直接写在一个匿名函数里。

控制器里写些什么?

我们也许写过这样的代码:

class IndexController extends Controller{

public function Index($content){

return '

'.$content.'';

}

}

复制代码

这样把界面的代码嵌入的写法是非常难以维护的,也是很多开发人员(包括我)最厌恶的写法,因为这种写法并没有做好界面与业务逻辑的分离,所以我们需要使用视图。

<?php foreach($data as $key=>$value){ ?>

复制代码

每一次调用控制器的某个方法时,render函数都会把参数以关联数组的形式传入,做到“业务逻辑”和“表现”的浅层次分离,但是这种分离还不是最好的,因为前端开发人员仍然需要面对甚至处理php代码,后端开发人员也有和前端人员沟通的成本,所以后面某一节,会再谈一种更好的分离方式。

php控制器和路由机制,自制PHP框架之路由与控制器相关推荐

  1. ASP.NET MVC3 学习心得------路由机制

    9.1 理解URL URL满足的要求: l 域名易于记忆和拼写 l 简短.易输入 l 可以反应出站点的结构 l 可破解,用户可以通过移除URL的末尾,进而达到更高层次的信息体系结构 l 持久.不能变化 ...

  2. Go Gin web框架的路由原理及中间件原理

    一.Gin框架的路由原理: 参考: go路由httprouter中的压缩字典树算法图解及c++实现 Golang-gin框架路由原理 首先了解下什么是路由? 简而言之,http路由即是一条http请求 ...

  3. java消息路由_SIP消息路由机制

    一:请求路由 松散路由(Loose Router)和严格路由(Strict Router),这是SIP协议(RFC3261)中的一个非常重要的概念. 在SIP消息的Route头域或Record-rou ...

  4. php框架中uri路由机制,URI 路由 — CodeIgniter 3.1.5 中文手册|用户手册|用户指南|中文文档...

    URI 路由¶ 一般情况下,一个 URL 字符串和它对应的控制器中类和方法是一一对应的关系. URL 中的每一段通常遵循下面的规则: example.com/class/function/id/ 但是 ...

  5. Razor视图引擎、控制器与路由机制学习

    1.1 千呼万唤始出来的MVC3.0 在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor.在这之前,我们一直在使用WebForm时代沿留下来的ASPX引擎或者第三方的NVelocity ...

  6. ASP.Net MVC开发基础学习笔记(3):Razor视图引擎、控制器与路由机制学习

    一.天降神器"剃须刀" - Razor视图引擎 1.1 千呼万唤始出来的MVC3.0 在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor.在这之前,我们一直在使用W ...

  7. php面试框架的执行流程图,ThinkPHP2.2框架执行流程图,ThinkPHP控制器的执行流程

    ThinkPHP2.2框架执行原理.流程图在线手册 ThinkPHP控制器的执行流程 对用户的第一次URL访问http:///My/index.php/Index/show/所执行的流程进行详细的分析 ...

  8. asp.net MVC 路由机制 Route

    1:ASP.NET的路由机制主要有两种用途: -->1:匹配请求的Url,将这些请求映射到控制器 -->2:选择一个匹配的路由,构造出一个Url 2:ASP.NET路由机制与URL重写的区 ...

  9. Android 的媒体路由功能应用与框架解析 MediaRouter

    一.功能描述 Android的媒体路由API被设计用来允许多种媒体(视频.音乐.图片)在与ANDROID设备连接(无线或有线)的辅助设备(如电视.立体声.家庭戏院系统.音乐播放机)上显示和播放,使用该 ...

最新文章

  1. hdu 5099 Comparison of Android versions 枚举题意
  2. git push origin与git push -u origin master的区别
  3. 最快捷的PPT技能提升之路 PPT定制 驼峰设计
  4. 面试笔记——C++11新特性
  5. 【转】asp.net mvc生成验证码
  6. Java面试题—内部类和静态内部类的区别
  7. 每日一笑 | 谷歌能严谨到什么地步?
  8. JBoss BRMS与JasperReports进行报告
  9. 世上描述宇宙最精确的科学理论
  10. Android 系统(174)---Android代码分析lint检查篇
  11. Django项目:CRM(客户关系管理系统)--83--73PerfectCRM实现CRM模板统一
  12. 笔记本显示器坏了,从硬盘安装win7系统
  13. 对软件未来走向的看法
  14. Java 编码规范8(编程规约-注释规约与其它)
  15. 游戏手柄延迟测试软件,六款免费网络延迟测试工具
  16. 查看python包的版本
  17. 数据结构与算法(零)-前言
  18. hp m281_惠普m281fdw驱动下载-hpm281fdw打印机驱动v44.3 官方版 - 极光下载站
  19. Docker-常用基础命令整理
  20. 数字金融企业绿色专利匹配数据(2011-2019)

热门文章

  1. alv导出本地文件DUMP
  2. ROA(资产收益率)与TCO(总所有成本)解析
  3. SAP ABAP逻辑数据库
  4. function收集
  5. 2021热度不减的在线教育,正在努力成为线下教育的有益补充
  6. python怎么处理数据_python panda怎么处理数据
  7. python读取表格数据_Python读取Excel数据并根据列名取值
  8. mysql列目录_mysql列直接存储图片路径
  9. flutter刷新页面_Flutter BottomNavigationBar切换会刷新当前页面解决方
  10. python实现进度条的3种方式