在做单一入口的时候,根据URI 对应的参数设置路由和控制器
- 思路
xx.com/index/index?name=test&age=22
将斜杠后面的第一个参数赋值为控制器,第二个参数赋值为控制器中的方法,
?后面的参数不需要处理,直接 _GET 参数,比如xx.com/index?name=test&age=22
,要做好处理,遇到问号,就直接返回即可
<?php
namespace Core\Lib;
/**
* 路由类
* Class Route
* @package Core\Lib
*/
class Route
{
/**
* @var string 控制器名 默认是 indexController
*/
public $controller = 'indexController';
/**
* @var string 方法名 默认是 index
*/
public $action = 'index';
/**
* xx.com/index/index
* 支持两种传参方式 如果传参,则必须写全控制器与方法
* Route constructor.
*/
public function __construct()
{
// $_SERVER['REQUEST_URI'] 这个值其实是一定会出现的,如果 url 只有站点,则显示 '/',代表访问首页
if (in_array($_SERVER['REQUEST_URI'], ['/', '/index.php'])) {
return true;
}
// 如果不在 ['/', '/index.php'],则代表肯定有值
$arr = explode('/', trim($_SERVER['REQUEST_URI'], '/'));
// / 后的第一个参数是控制器名
if (isset($arr[0])) {
if (mb_strpos($arr[0], '?') !== false) {
list($controller, $request_get) = explode('?', $arr[0]);
$this->controller = $controller. 'Controller';
// 如果有问号,则表示使用的默认控制器和方法
return true;
}
$this->controller = $arr[0] . 'Controller';
}
unset($arr[0]);
// 第二个参数是控制器方法
if (isset($arr[1])) {
if (mb_strpos($arr[1], '?') !== false) {
list($method, $request_get) = explode('?', $arr[1]);
$this->action = $method;
// 表示有问号传值
return true;
} else {
$this->action = $arr[1];
}
}
// 第三个参数是 回调对应的 Service ,是哦自己项目中使用到的一个参数值
if (isset($arr[2])) {
if (mb_strpos($arr[2], '?') !== false) {
// 表示有问号传值
list($service, $request_get) = explode('?', $arr[2]);
$_ENV['service'] = $service;
} else {
$_ENV['service'] = $arr[2];
}
}
// 以下方式是设置成 /key/value 的这种形式的。
// if (!$_GET) {
// // 如果使用 ? 方式传递参数,则不再处理
// unset($arr[1]);
// // url 多余部分转换成 get 参数 index/index/id/1
// // 重新获取控制器和方法以外的参数,奇数是值,奇数加1是键,
// $i = 2;
// while (isset($arr[$i])) {
// if (!isset($arr[$i + 1])) {
// // 不存在这个键,则肯定到此为止了
// $get_values[$arr[$i]] = '';
// break;
// }
// $_GET[$arr[$i]] = $arr[$i + 1];
// $i = $i + 2;
// }
// }
}
}
应用
// 获取路由
$route = new Route();
// 2.判断控制器是否存在
$class = '/App/Controller/' . $route->controller;
if (!is_file(BASE_PATH . $class . '.php')) {
self::responseError('路由不存在', -401);
}
$class = str_replace('/', '\\', $class);
$controller = new $class();
// 3.判断控制器中的方法是否存在
$action = $route->action;
if (!method_exists($controller, $action)) {
self::responseError('路由不存在', -402);
}
// 4. 请求控制器中的方法
$response = call_user_func([$controller, $route->action]);
// 正常返回肯定是数组形式,不会执行到这一步
if (!is_array($response)) {
self::responseError('返回数据格式有误,请联系客服,谢谢!', -501);
}
// 如果 返回的是 responseError status !==200 则表示返回有误,记录错误日志 回调中有可能没有 status 状态
$response['status'] = isset($response['status']) ? $response['status'] : -10001;
if ($response['status'] !== 200) {
app_log($response, Log::LOG_RESPONSE_ERROR);
}
echo json_encode($response, JSON_UNESCAPED_UNICODE);
die;
使用 composer 实现自动加载即可,不需要自己再使用 spl_autoload_register()
函数
composer.json
{
"autoload": {
"psr-4": {
"App\\": "app/",
"Core\\": "core/"
},
"files": [
"core/common/function.php"
]
}
}
执行 composer autoload
网友评论