自定义路由
BeaconPHP 的路由规则是允许自定义的,要自定义路由我们需要用到 Route 路由类。
一个自定义路由的完整代码如下。
use beacon\core\App;
use beacon\core\Route;
#设置时区
date_default_timezone_set('PRC');
###开发可打开调试模式,上线时一定要关闭
const DEV_DEBUG = true;
#调试日志输出
const DEBUG_LOG = true;
#调试sql语句输出
const DEBUG_MYSQL_LOG = true;
#使用 REDIS_SESSION
const USE_REDIS_SESSION = false;
#定义根目录
define('ROOT_DIR', dirname(__DIR__));
#以上定义常量---------
#引入composer 启动文件
require(ROOT_DIR . '/vendor/autoload.php');
#定义路由
$route = new Route('home', '/');
$route->addRule([
#键名是一个正则表达式,值是一个数组,其中 $1 $2 .. 表示从表达式括号中抽取相应的内容。 除了必须要设置 ctl act 以外 还可以设置其他参数,其他参数将写入到 $_GET 中。
#如这个表达式是请求路径 /abc/32333 执行的是 控制器 index 操作 index 参数 id=32333
'@^/abc/(\d+)@' => ['ctl' => 'index', 'act' => 'index', 'id' => '$1'],
#这个表达式是 请求 / 执行的控制器是 index 操作是 index
'@^/@' => ['ctl' => 'index', 'act' => 'index']
]);
App::reg($route);
App::route('admin', '/admin');
App::route('service', '/service');
#运行应用
App::run();
约定:
其中 ctl 和 act 在路由规则定义中 必须指定,可以是 替换符 $1 $2 $... zi取表达式括号中的内容。
ctl 不可以使用大写 如果控制器是 MyBook 对应的小写+下划线 是 my_book
如果是Mybook对应的是mybook
操作act也不能使用大写,只能是小写+下划线。
自定义路由在项目中如果不是特殊要求,一般不会去自定义,为了性能考虑,直接使用正则表达式来定义,这里设计没有使用其他路由定义的符号定义,主要是考虑到性能问题。
自定义路由的URL生成
由于自定义路由,所以对于虚拟URL转换到真实的URL 默认的转换规则已经不再适用,所以我们这里需要设置一个转换函数用于生成对应的模板URL
注意生成的是 URL 的模板而不是url 本身
如:
/{ctl}/{act}/{id} 或者 /{ctl}/{act}_{id} 这个是URL模板
我们需要设置一个用于生成URL模板的方法。
function (string $ctl, string $act, array $param)
$ctl 是控制器,$act 是操作,$param 是参数键值对
例如 我们默认的规则是
function (string $ctl, string $act, array $param) {
$url = '/{ctl}';
if (!empty($act) && $act != 'index') {
$url .= '/{act}';
}
return $url;
}
# 即如果有控制器和操作名称 就返回 /{ctl}/{act}
# 如果只有控制器没有操作名称 就返回 /{ctl}
那么依据上面我们自定义的路由规则
我们希望 如果是 ctl == index ,act == index (或者为空) 且 有 id存在的时候 url 反解析为 /abc/{id}
如果没有 id 的时候 直接返回 /
反解析生成URL模板函数如下:
function (string $ctl, string $act, array $param) {
if ($ctl == 'index' && (empty($act) || $act == 'index') && isset($param['id'])) {
return '/abc/{id}';
}
return '/';
}
完整的路由代码如下:
use beacon\core\App;
use beacon\core\Route;
#设置时区
date_default_timezone_set('PRC');
###开发可打开调试模式,上线时一定要关闭
const DEV_DEBUG = true;
#调试日志输出
const DEBUG_LOG = true;
#调试sql语句输出
const DEBUG_MYSQL_LOG = true;
#使用 REDIS_SESSION
const USE_REDIS_SESSION = false;
#定义根目录
define('ROOT_DIR', dirname(__DIR__));
#以上定义常量---------
#引入composer 启动文件
require(ROOT_DIR . '/vendor/autoload.php');
#定义路由
$route = new Route('home', '/');
$route->addRule([
#键名是一个正则表达式,值是一个数组,其中 $1 $2 .. 表示从表达式括号中抽取相应的内容。 除了必须要设置 ctl act 以外 还可以设置其他参数,其他参数将写入到 $_GET 中。
#如这个表达式是请求路径 /abc/32333 执行的是 控制器 index 操作 index 参数 id=32333
'@^/abc/(\d+)@' => ['ctl' => 'index', 'act' => 'index', 'id' => '$1'],
#这个表达式是 请求 / 执行的控制器是 index 操作是 index
'@^/@' => ['ctl' => 'index', 'act' => 'index']
]);
#设置反解析URL函数,返回的是URL模板
$route->setResolve(function (string $ctl, string $act, array $param) {
if ($ctl == 'index' && (empty($act) || $act == 'index') && isset($param['id'])) {
return '/abc/{id}';
}
return '/';
});
App::reg($route);
App::route('admin', '/admin');
App::route('service', '/service');
#运行应用
App::run();
设置好反解析后:
class Index extends Controller
{
/**
* 使用模板
* @return string
*/
#[Method(act: 'index', method: Method::GET)]
public function index()
{
echo App::url(['ctl' => 'index', 'act' => 'index', 'id' => 3, 'name' => 'wj008']) . '</br>';
echo App::url(['ctl' => 'index', 'act' => 'index', 'name' => 'wj008']) . '</br>';
}
}
最终生成的真实URL 如下:
/abc/3?name=wj008
/?name=wj008