<?php /** * 路由解析类 * 1.路由解析 * 2.请求分发 */ namespace pig; class Route { //路由信 protected $route = []; //pathinfo //public $pathInfo = []; protected $pathInfo = []; //URL参数 //public $params = []; protected $params = []; //构造方法 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'] * 参数数组:$this->params = ['name'=>'peter','age'=>30] */ //第一步:将查询字符串前后的/去掉,再按分隔符/拆分到数组中 $queryStr = trim(strtolower($queryStr),'/'); $queryArr = explode('/',$queryStr);//拆分成数组 //$queryArr = array_filter($queryArr); //第二步:解析出$queryArr数组中的内容(模块,控制器,操作,参数) switch(count($queryArr)) { //没有参数,则使用默认模块/控制器/操作 case 0: $this->pathInfo = $this->route; break; //只有一个参数:用户只提供模块,控制器和操作使用默认值 case 1: $this->pathInfo['module'] = $queryArr[0]; break; //二个参数:模块和控制器自定义的,操作是默认的 case 2: $this->pathInfo['module'] = $queryArr[0]; $this->pathInfo['controller'] = $queryArr[1]; break; //三个参数:模块/控制器/操作全部自定义:全部来自用户的实际请求 case 3: $this->pathInfo['module'] = $queryArr[0]; $this->pathInfo['controller'] = $queryArr[1]; $this->pathInfo['action'] = $queryArr[2]; break; //对参数进行处理 default: $this->pathInfo['module'] = $queryArr[0]; $this->pathInfo['controller'] = $queryArr[1]; $this->pathInfo['action'] = $queryArr[2]; //从pathinfo数组的索引3开始,将剩余的元素全部作为参数进行处理 $arr = array_slice($queryArr,3); //键值对必须成对出现,所以每次递增2 for($i=0;$i<count($arr);$i+=2){ //如果没有第二个参数,则放弃 if(isset($arr[$i+1])){ $this->params[$arr[$i]] = $arr[$i+1]; } } break; } //返回当前路由类的实例对象,主要是方便链式调用: //$route->parse();$route->worm();$route->print() return $this; } //请求分发 public function dispatch() { //生成的带有命名空间的控制器类名称:app\模块\controller\控制器类 //类名称应该与类文件的绝对路径一一对应,这样才可以实现自动映射,方便自动加载 //模块名称 $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: /'); } //将用户的请求分发到指定的控制器和操作方法上 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); //测试请求分发 require __DIR__.'/../app/admin/controller/Index.php'; echo $route->dispatch();*/
<?php /** * 框架基础类 * 1.调试模式 * 2.自动加载 * 3.启动框架 */ namespace pig; class Base { //框架配置 protected $config = []; //路由信息 protected $queryStr = ''; //构造方法 public function __construct($config,$queryStr='') { $this->config = $config; $this->queryStr = $queryStr; } //设置调试模式 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'; //如果没有找到类文件,就直接返回默认首页 if(!file_exists($path)){ header('Location: /'); } require $path; } //启动框架 public function run() { //调试模式 $this->setDebug(); //自动加载 spl_autoload_register([$this,'loader']); //请求分发 echo (new Route($this->config['route']))->parse($this->queryStr)->dispatch(); } }
<?php /** * 配置文件:适用于整个应用 * 采用PHP数组方式返回数据 */ return [ //应用配置 'app' => [ //调试开关 'debug'=>true, ], //路由配置 'route' => [ //默认模块 'module' => 'admin', //默认控制器 'controller' => 'Index', //默认操作 'action' => 'index', ], //数据库配置 'db' => [ //数据库的类型 'database_type' => 'mysql', //默认的数据库名称 'database_name' => 'frame', //默认的主机名 'server' => '127.0.0.1', //默认的用户名 'username' => 'root', //用户密码 'password' =>'root', //默认的客户端的字符集编码 'charset' => 'utf8', //默认服务端口号 'port' => 3306, ] ];
框架的核心文件:框架的配置文件(以数组的形式完成整个应用的配置,路由,数据库等),路由类(路由解析和请求分发)和基础类(调试模式,自动加载和启动框架)文件,还有入口文件(定义常量,加载函数库,启动框架,使启动框架有统一的入口),还有创建框架的模型基类(实例化数据库框架),视图基类(实例化视图模型),控制器基类(实现模板引擎的配置,模板赋值(将参数保存在数组)和模板渲染(将数组键值对转换为变量的名值对,然后加载模板文件)。至此,一个小型的框架就完成,然后就可以建立自己的项目啦。学完这章,对框架的整体建立和运行过程有一个基本的认识,懂得其中的原理,为学习其他框架提供了基础。至此,php基础也学完了,学到了很多东西,感谢老师的辛苦讲解和付出,为我以后的php道路打下了扎实的基础。有老师陪伴,学习的时间真的很开心,很充实。