abstract:<?php /** * 路由解析類 * 1.路由解析 * 2.請求分發(fā) */ namespace pig; class Route { //路由信 protected $route =&nbs
<?php /** * 路由解析類 * 1.路由解析 * 2.請求分發(fā) */ namespace pig; class Route { //路由信 protected $route = []; //pathinfo //public $pathInfo = []; protected $pathInfo = []; //URL參數(shù) //public $params = []; protected $params = []; //構(gòu)造方法 public function __construct($route) { $this->route = $route; } //解析路由 public function parse($queryStr='') { /** * /admin/user/add/name/peter/age/30 * $this->pathInfo=['module'=>'admin','controller'=>'user','action'=>'add'] * 參數(shù)數(shù)組:$this->params = ['name'=>'peter','age'=>30] */ //第一步:將查詢字符串前后的/去掉,再按分隔符/拆分到數(shù)組中 $queryStr = trim(strtolower($queryStr),'/'); $queryArr = explode('/',$queryStr);//拆分成數(shù)組 //$queryArr = array_filter($queryArr); //第二步:解析出$queryArr數(shù)組中的內(nèi)容(模塊,控制器,操作,參數(shù)) switch(count($queryArr)) { //沒有參數(shù),則使用默認(rèn)模塊/控制器/操作 case 0: $this->pathInfo = $this->route; break; //只有一個參數(shù):用戶只提供模塊,控制器和操作使用默認(rèn)值 case 1: $this->pathInfo['module'] = $queryArr[0]; break; //二個參數(shù):模塊和控制器自定義的,操作是默認(rèn)的 case 2: $this->pathInfo['module'] = $queryArr[0]; $this->pathInfo['controller'] = $queryArr[1]; break; //三個參數(shù):模塊/控制器/操作全部自定義:全部來自用戶的實際請求 case 3: $this->pathInfo['module'] = $queryArr[0]; $this->pathInfo['controller'] = $queryArr[1]; $this->pathInfo['action'] = $queryArr[2]; break; //對參數(shù)進(jìn)行處理 default: $this->pathInfo['module'] = $queryArr[0]; $this->pathInfo['controller'] = $queryArr[1]; $this->pathInfo['action'] = $queryArr[2]; //從pathinfo數(shù)組的索引3開始,將剩余的元素全部作為參數(shù)進(jìn)行處理 $arr = array_slice($queryArr,3); //鍵值對必須成對出現(xiàn),所以每次遞增2 for($i=0;$i<count($arr);$i+=2){ //如果沒有第二個參數(shù),則放棄 if(isset($arr[$i+1])){ $this->params[$arr[$i]] = $arr[$i+1]; } } break; } //返回當(dāng)前路由類的實例對象,主要是方便鏈?zhǔn)秸{(diào)用: //$route->parse();$route->worm();$route->print() return $this; } //請求分發(fā) public function dispatch() { //生成的帶有命名空間的控制器類名稱:app\模塊\controller\控制器類 //類名稱應(yīng)該與類文件的絕對路徑一一對應(yīng),這樣才可以實現(xiàn)自動映射,方便自動加載 //模塊名稱 $module = $this->pathInfo['module']; $controller ='app\\'.$module.'\controller\\'.ucfirst($this->pathInfo['controller']); //操作名 $action = $this->pathInfo['action']; //判斷該類中是否有這個方法存在 if(!method_exists($controller,$action)){ $action = $this->route['action']; header('location: /'); } //將用戶的請求分發(fā)到指定的控制器和操作方法上 return call_user_func_array([new $controller,$action],$this->params); } //獲取pathinfo public function getPathInfo() { return $this->pathInfo; } //獲取模塊 public function getModule() { return $this->pathInfo['module'] ? : $this->route['module']; } //獲取控制器名稱 public function getController() { return 'app\\'.$this->getModule().'\controller\\'.ucfirst($this->pathInfo['controller']); } } /*//測試路由 $queryStr = $_SERVER['QUERY_STRING']; echo $queryStr; echo '<hr>'; echo '<pre>'; print_r(explode('/',$queryStr)); $config = require 'config.php'; $route = new Route($config['route']); $route->parse($queryStr); /*print_r($route->pathInfo); print_r($route->params); //測試請求分發(fā) require __DIR__.'/../app/admin/controller/Index.php'; echo $route->dispatch();*/
<?php /** * 框架基礎(chǔ)類 * 1.調(diào)試模式 * 2.自動加載 * 3.啟動框架 */ namespace pig; class Base { //框架配置 protected $config = []; //路由信息 protected $queryStr = ''; //構(gòu)造方法 public function __construct($config,$queryStr='') { $this->config = $config; $this->queryStr = $queryStr; } //設(shè)置調(diào)試模式 public function setDebug() { //debug == true if($this->config['app']['debug']){ error_reporting(E_ALL); ini_set('display_errors','On'); }else{ //error_reporting(E_ALL); ini_set('display_errors','Off'); ini_set('log_errors','on'); } } //注冊自動加載器:自動加載的是類 public function loader($class) { //new \app\admin\controller\Stu(), app/admin/controller/Stu.pho $path = ROOT_PATH.str_replace('\\','/',$class).'.php'; //如果沒有找到類文件,就直接返回默認(rèn)首頁 if(!file_exists($path)){ header('Location: /'); } require $path; } //啟動框架 public function run() { //調(diào)試模式 $this->setDebug(); //自動加載 spl_autoload_register([$this,'loader']); //請求分發(fā) echo (new Route($this->config['route']))->parse($this->queryStr)->dispatch(); } }
<?php /** * 配置文件:適用于整個應(yīng)用 * 采用PHP數(shù)組方式返回數(shù)據(jù) */ return [ //應(yīng)用配置 'app' => [ //調(diào)試開關(guān) 'debug'=>true, ], //路由配置 'route' => [ //默認(rèn)模塊 'module' => 'admin', //默認(rèn)控制器 'controller' => 'Index', //默認(rèn)操作 'action' => 'index', ], //數(shù)據(jù)庫配置 'db' => [ //數(shù)據(jù)庫的類型 'database_type' => 'mysql', //默認(rèn)的數(shù)據(jù)庫名稱 'database_name' => 'frame', //默認(rèn)的主機名 'server' => '127.0.0.1', //默認(rèn)的用戶名 'username' => 'root', //用戶密碼 'password' =>'root', //默認(rèn)的客戶端的字符集編碼 'charset' => 'utf8', //默認(rèn)服務(wù)端口號 'port' => 3306, ] ];
框架的核心文件:框架的配置文件(以數(shù)組的形式完成整個應(yīng)用的配置,路由,數(shù)據(jù)庫等),路由類(路由解析和請求分發(fā))和基礎(chǔ)類(調(diào)試模式,自動加載和啟動框架)文件,還有入口文件(定義常量,加載函數(shù)庫,啟動框架,使啟動框架有統(tǒng)一的入口),還有創(chuàng)建框架的模型基類(實例化數(shù)據(jù)庫框架),視圖基類(實例化視圖模型),控制器基類(實現(xiàn)模板引擎的配置,模板賦值(將參數(shù)保存在數(shù)組)和模板渲染(將數(shù)組鍵值對轉(zhuǎn)換為變量的名值對,然后加載模板文件)。至此,一個小型的框架就完成,然后就可以建立自己的項目啦。學(xué)完這章,對框架的整體建立和運行過程有一個基本的認(rèn)識,懂得其中的原理,為學(xué)習(xí)其他框架提供了基礎(chǔ)。至此,php基礎(chǔ)也學(xué)完了,學(xué)到了很多東西,感謝老師的辛苦講解和付出,為我以后的php道路打下了扎實的基礎(chǔ)。有老師陪伴,學(xué)習(xí)的時間真的很開心,很充實。
Correcting teacher:滅絕師太Correction time:2019-03-21 09:08:24
Teacher's summary:希望你們通過自己的努力,都成為行業(yè)佼佼者,前路還長,繼續(xù)加油!