摘要:<?php /** * 路由解析类 * 1.路由解析 * 2.请求分发 */ namespace pig; class Route { //路由信 protected $route =&nbs
<?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道路打下了扎实的基础。有老师陪伴,学习的时间真的很开心,很充实。
批改老师:灭绝师太批改时间:2019-03-21 09:08:24
老师总结:希望你们通过自己的努力,都成为行业佼佼者,前路还长,继续加油!