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