我们为什么要使用路由?原因1:一个更漂亮的URI
1.URI的改进
刚刚开始学PHP时,我们一定写过blog.php"htmlcode">
www.mysite.com/blog.php"htmlcode">www.mysite.com/blog/1这种URI是目前最流行的URI,举个例子,比如很多读书类,电影类网站,都使用了这样的URI,这样的URI要比index.php"htmlcode">
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对应了一个方法,但是我们常常遇到这样的问题:
<"htmlcode">class IndexController extends Controller{ public function Index($content){ return '<html><head></head><body>'.$content.'</body></html>'; } }这样把界面的代码嵌入的写法是非常难以维护的,也是很多开发人员(包括我)最厌恶的写法,因为这种写法并没有做好界面与业务逻辑的分离,所以我们需要使用视图。
<html> <head> </head> <body> <?php foreach($data as $key=>$value){ ?> <div> <?php echo $key.':'.$value; ?> </div> <?php } ?> </body> </html>每一次调用控制器的某个方法时,render函数都会把参数以关联数组的形式传入,做到“业务逻辑”和“表现”的浅层次分离,但是这种分离还不是最好的,因为前端开发人员仍然需要面对甚至处理PHP代码,后端开发人员也有和前端人员沟通的成本,所以后面某一节,会再谈一种更好的分离方式。
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。