- 相關(guān)推薦
PHP框架之路由與控制器詳解
路由與控制器之間是什么關(guān)系?為什么使用路由?下面是由百分網(wǎng)小編為大家整理的PHP框架之路由與控制器,喜歡的可以收藏一下!了解更多詳情資訊,請(qǐng)關(guān)注應(yīng)屆畢業(yè)生考試網(wǎng)!
我們?yōu)槭裁匆褂寐酚桑?/strong>
原因1:一個(gè)更漂亮的URI
1.URI的改進(jìn)
剛剛開(kāi)始學(xué)PHP時(shí),我們一定寫(xiě)過(guò)blog.php?id=1之類(lèi)的URI,使用GET方式獲取參數(shù)。這樣的URI有兩個(gè)缺點(diǎn),一是容易被SQL注射攻擊,二是維護(hù)性可讀性差,大家可以比較下面兩種URI哪一種更具備可讀性。
www.mysite.com/blog.php?id=1
上面URI是我們初學(xué)PHP最常用的。
www.mysite.com/blog/1
這種URI是目前最流行的URI,舉個(gè)例子,比如很多讀書(shū)類(lèi),電影類(lèi)網(wǎng)站,都使用了這樣的URI,這樣的URI要比index.php?a=1&b=2&c=3&d=4....要簡(jiǎn)潔很多。
2.實(shí)現(xiàn)方法
在WEB項(xiàng)目的根目錄下寫(xiě)一個(gè).htaccess文件
RewriteEngine On
RewriteRule ^([a-zA-Z0-9/]*)$ index.php/$1
重寫(xiě)規(guī)則,讓域名后面的字符串直接做為一個(gè)參數(shù)傳入index.php,這樣index.php就成為了你整個(gè)WEB應(yīng)用的中心,定義了“請(qǐng)求和響應(yīng)的映射”。
原因2:?jiǎn)我蝗肟跈C(jī)制的易維護(hù)性
1.路由數(shù)組
一個(gè)PHP初學(xué)者,剛開(kāi)始做項(xiàng)目,項(xiàng)目做著做著規(guī)模做大了,常常這個(gè)PHP頁(yè)面給另一個(gè)PHP頁(yè)面用GET方法傳值,有時(shí)傳的值還不止一個(gè),時(shí)間一久,你的WEB項(xiàng)目,N個(gè)PHP頁(yè)面宛如一個(gè)復(fù)雜的蜘蛛網(wǎng),讓你難以維護(hù)。一旦有修改,會(huì)涉及很多PHP文件,工作量很大。
MVC的單一入口機(jī)制可以解決維護(hù)難的問(wèn)題,路由就是一套映射,可以讓你一個(gè)URI對(duì)應(yīng)一個(gè)方法。
$route=[
''=>'IndexController@Index',
'blog'=>'BlogController@Show',
'blog/{id}/{name}'=>'BlogController@Show',
];
2.獲取參數(shù)
$path=$_SERVER['PATH_INFO'];
$path=ltrim($path,'/');
echo $path.PHP_EOL;
我們?cè)跒g覽器里輸入:www.mysite.com/blog/1后,path變量為/blog/1。使用ltrim函數(shù)刪除左邊的斜杠,然后使用explode把字符串拆解成數(shù)組。
$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函數(shù)可以銷(xiāo)毀數(shù)組中key和value,但是并不會(huì)重建索引,所以path_arr[0]是要調(diào)用的控制器類(lèi)和方法名,path_arr[1]或者path_arr[1..N]就作為傳入方法的參數(shù)。
重定向和錯(cuò)誤頁(yè)面是WEB系統(tǒng)中最常見(jiàn)的,如果不用路由機(jī)制,你可能要沒(méi)完沒(méi)了的重復(fù)寫(xiě)重定向或者錯(cuò)誤頁(yè)面的顯示或者跳轉(zhuǎn)代碼,有了路由,只需要一句話就可以完成。
原因3:減少資源的消耗
MVC采用了控制器(controller)來(lái)響應(yīng)請(qǐng)求(request),每次請(qǐng)求來(lái)時(shí),應(yīng)該在指定的一個(gè)PHP文件中初始化這個(gè)控制器,而不是分別在不同的PHP文件中做初始化工作,這樣可以減少資源的消耗。
是不是一定要用控制器?
方案1:不用控制器
我們現(xiàn)在路由數(shù)組里添加一項(xiàng),value不是一個(gè)字符串,而是一個(gè)匿名函數(shù)(Closure)
$route=[
''=>'Index',
'blog'=>'BlogController@Show',
'blog/{id}/{name}'=>'BlogController@Show',
'f'=>function(){echo 'hello';}
];
這里的route[f]是一個(gè)匿名函數(shù),并不是一個(gè)控制器類(lèi)的方法,所以,我們要把上一節(jié)路由代碼做一下修改:
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一個(gè)html頁(yè)面是一件很不優(yōu)雅的事情,所以我們寫(xiě)一個(gè)render函數(shù)
function render($path,array $args){
extract($args);
require($path);
}
我們知道每個(gè)URI對(duì)應(yīng)了一個(gè)方法,但是我們常常遇到這樣的問(wèn)題:
<?php
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]);
}
}
?>
用不用控制器,取決于你的業(yè)務(wù)復(fù)雜度。個(gè)人建議使用控制器,但是對(duì)于業(yè)務(wù)很簡(jiǎn)單的頁(yè)面跳轉(zhuǎn)或檢查,可以直接寫(xiě)在一個(gè)匿名函數(shù)里。
控制器里寫(xiě)些什么?
我們也許寫(xiě)過(guò)這樣的代碼:
class IndexController extends Controller{
public function Index($content){
return '<html><head></head><body>'.$content.'</body></html>';
}
}
這樣把界面的代碼嵌入的寫(xiě)法是非常難以維護(hù)的,也是很多開(kāi)發(fā)人員(包括我)最厭惡的寫(xiě)法,因?yàn)檫@種寫(xiě)法并沒(méi)有做好界面與業(yè)務(wù)邏輯的分離,所以我們需要使用視圖。
<html>
<head>
</head>
<body>
<?php foreach($data as $key=>$value){ ?>
<p>
<?php echo $key.':'.$value; ?>
</p>
<?php } ?>
</body>
</html>
每一次調(diào)用控制器的某個(gè)方法時(shí),render函數(shù)都會(huì)把參數(shù)以關(guān)聯(lián)數(shù)組的形式傳入,做到“業(yè)務(wù)邏輯”和“表現(xiàn)”的淺層次分離,但是這種分離還不是最好的,因?yàn)榍岸碎_(kāi)發(fā)人員仍然需要面對(duì)甚至處理PHP代碼,后端開(kāi)發(fā)人員也有和前端人員溝通的成本,所以后面某一節(jié),會(huì)再談一種更好的分離方式。
【PHP框架之路由與控制器詳解】相關(guān)文章:
php路由與控制器分析08-11
PHP中Yii框架之表單驗(yàn)證規(guī)則06-08
PHP框架的概念07-11
PHP數(shù)據(jù)類(lèi)型之?dāng)?shù)組變量詳解10-04
如何使用PHP框架09-12
PHP框架是什么09-23
php框架Phpbean說(shuō)明09-30