路由
TubePress 路由 API:前台、后台与 API 路由如何注册、匹配与分发,包括路由参数与 HTTP 方法。
TubePress 使用一个围绕静态 Router 类构建的轻量、高速路由器。控制器在 ::routes() 方法中注册其路由,public/index.php 在分发请求前调用这些方法。本页涵盖了从插件中添加路由或了解请求如何匹配所需的全部内容。
注册路由
使用 Router::get() 或 Router::post() 注册路由。处理器可以是任意可调用对象——闭包或 [Class, 'method'] 对。
// Closure handler
Router::get('/promo', function () {
ThemeRenderer::render('promo', ['deal' => 'Summer']);
});
// Controller handler
Router::post('/promo/claim', [PromoController::class, 'claim']);按照惯例,每个控制器都暴露一个静态 routes() 方法来注册所有路由,该方法在启动时调用一次:
class PromoController
{
public static function routes(): void
{
Router::get('/promo', [self::class, 'show']);
Router::post('/promo/claim', [self::class, 'claim']);
}
}路由参数
在路径中使用 {name} 占位符,每个占位符匹配单个 URL 段(除 / 外的所有内容)。使用 Router::param() 读取参数值。
Router::get('/promo/{code}', function () {
$code = Router::param('code'); // required
$ref = Router::param('ref', 'direct'); // with a default
// …
});在内部,像 /promo/{code} 这样的模式会被编译为正则表达式 (?P<code>[^/]+),因此参数不会跨越斜杠。精确路由优先匹配,之后按注册顺序匹配参数化路由。
发送响应
| 方法 | 用途 |
|---|---|
ThemeRenderer::render($tpl, $data) | 通过当前激活主题渲染前端页面。 |
Router::render($tpl, $data) | 渲染管理后台模板(templates/{$tpl}.php)。 |
Router::json($data, $code = 200) | 发送 JSON 响应并退出。 |
Router::redirect($url) | 重定向(并退出)。前端 URL 将自动添加当前语言/类型前缀。 |
路由顺序与全局捕获
静态页面由 /{slug} 全局捕获路由处理,因此页面控制器在 public/index.php 中被最后注册——在所有前端、管理后台和 API 路由之后。如果在启动期间从插件中注册路由,这些路由会被添加在全局捕获之前,因此会优先匹配。
/deals 这样的插件路由会遮蔽 /deals 处的静态页面。为安全起见,请为插件路由添加命名空间(例如 /promo/deals)。CSRF 防护
每个会更改状态的 POST 请求都应受到 CSRF 防护。路由器提供了以下辅助方法:
// In your form template
<?= Router::csrfField() ?> // hidden input
// In your POST handler
if (!Router::verifyCsrf()) {
Router::json(['error' => 'Invalid token'], 403);
}verifyCsrf() 接受来自 csrf_token POST 字段或 X-CSRF-Token 请求头的令牌,并使用 hash_equals() 进行比较。
本地化与类型化 URL
对于多语言站点,路由器会透明地处理语言前缀(例如 /fr/…)并翻译已知路由 slug,因此 /categorie/brunette 会解析到 category 路由。管理后台和安装路由不受此影响——如需让自定义路径跳过前缀处理,请使用 Router::addNoPrefixPath() 注册该路径。详见语言与翻译了解完整行为。辅助方法 Router::langPrefix()、Router::typePrefix() 和 Router::url() 可帮助您在任意语言环境下构建正确的链接。