前端控制器模式就是给你的 web 应用程序设置单一的入口(比如 index.php),用来集中处理所有请求的机制,目前大多数的PHP框架是这种形式。
它的职责是载入所有依赖,处理请求,并发送响应给浏览器。前端控制器模式对整个架构是有益的,因为它鼓励模块化代码,并给了你一个单入口,可以写一些每个请求都需要跑的代码(比如输入数据的过滤)。
前端控制器:单一入口,定义了一个中心入口文件,每个请求都需要从这个入口进入系统,当然也可以在这里对用户的输入请求进行过滤。前端控制器处理请求后选择适当的命令(处理业务的)。在PHP中,这种模式每次都需要初始化,所以会导致性能的下降,但好处还是显而易见的。
前端控制器处理的是请求,那么我们就需要把用户的请求进行处理。
<?php class Demo { private static $_instance; public static $classMap; public static $dirMap = array(); public function __construct() { self::$classMap = array( 'Component'=>'/core/Component.php', 'controllers\Controller'=>'/core/Controller.php', 'models\Model'=>'/core/Model.php', ); } public static function run() { self::$_instance = new self; self::import('controllers'); self::import('models'); } public static function route() { $request_uri = $_SERVER['REQUEST_URI']; $route = preg_replace("/.*c.php\/?/",'',$request_uri); $route = preg_replace("/\?.*/",'',$route); $route = trim($route,'/'); empty($route) && $route = 'site/index'; $routeArr = explode('/',$route); $controllerName = ''; $dir = 'controllers'; for($i=0,$c=count($routeArr);$i<$c;$i++) { if(in_array($dir.'.'.$routeArr[$i], self::$dirMap)){ $dir .= '.'.$routeArr[$i]; continue; } $controllerName .= $dir.'.'.ucfirst($routeArr[$i]).'Controller'; break; } $controllerName = preg_replace('/\./','\\',$controllerName); if($i+1 == $c){ $actionId = 'index'; }else{ $actionId = $routeArr[$i+1]; } $actionName = ucfirst($actionId); if(!class_exists($controllerName)){ self::err_404(); } $obj = new $controllerName(); if(!method_exists($obj, $actionName)){ self::err_404(); } $obj->$actionName(); } public static function import($dir) { $files = scandir(dirname(__DIR__).DIRECTORY_SEPARATOR.$dir); foreach($files as $v) { if($v=='.' || $v=='..') continue; if(is_dir($dir.'/'.$v)){ $dotDir = preg_replace('/\//','.',$dir.'/'.$v); in_array($dotDir,self::$dirMap) || self::$dirMap[] = $dotDir; self::import($dir.'/'.$v); continue; } $classname = substr($v,0,strpos($v,'.php')); $classname =preg_replace('/\//','\\',$dir).'\\'.$classname; self::$classMap[$classname] = '/'.$dir.'/'.$v; } } public static function appendClassmap($arr=array()) { self::$classMap = array_merge(self::$classMap,$arr); } public static function isAjax() { return isset($_POST['ajax']); } public static function autoload($className) { if(isset(static::$classMap[$className])){ $classFile = static::$classMap[$className]; }else{ $classFile = DIRECTORY_SEPARATOR.$className.'.php'; } $classFile = dirname(__DIR__).$classFile; if(!is_file($classFile)){ return; } include($classFile); } public static function err_404() { echo '404 Not Found!'; die; } } //SPL注册自动加载 spl_autoload_register(['Demo', 'autoload'], true, true);
现在,只要在一个php文件中包含这个类文件,运行就可以了。
<?php require 'core/Demo.php'; Demo::run(); Demo::route();//路由