路由及过滤器
一、路由
Hymie PHPMVC 框架使用正则表达式定义路由。框架支持两种路由配置方式
-
配置文件
config.router.php
- 注解 @RouterMapping(value="...")
基于框架开发的应用由一到多个模块组成,路由则定义在每个模块的 config.router.php
配置文件中。
路由定义采用正则表达式方式,请参考 配置文件 章节示例。
1.1 路由的处理方式
-
环境区别
在config.php
中$config]'debug']
为true
时,框架不缓存路由信息,为false
时,框架会使用缓存 bean 缓存路由信息,记录路由请求次数,按照请求次数进行排序。也就是请求最多的路由会排在最前面,这样可以一定程度上提升路由解析的效率。 -
加载流程 框架启动后,会检查缓存中是否有路由配置,如有则加载,如没有则处理每个模块下的
config.router.php
文件,合并成路由表。框架在开发模式和正式模式下都会检查缓存路由表,只不过开发模式下使用的缓存是
\hymie\cache\ArrayCache
类,因此检查使用为false
- 路由处理流程
框架会循环路由表中的路由,逐个匹配当前路径,若匹配则解析生成控制器实例、模块名、控制器方法反射对象、控制器方法参数数组等数据给
Application
对象,后者会调用控制器方法,并寻找对应模块下的视图文件渲染视图。
注:因此,每个模块只能定义自己模块下的路由。例外情况是,如果路由对应的控制器返回
json
视图,或者在控制器直接输出数据,或者跳转地址的情况可以不受此限制。
1.2 路由配置文件
在 配置文件 章节介绍了各种配置文件,这里针对路由配置再做一些介绍。
-
应用中至少一个模块需要有路由定义。
-
没有路由定义的模块可以理解为类库。
- 模块的路由定义文件名为
config.router.php
,包含它时必须返回数组形式数据。
如果团队开发,担心多人编辑 config.router.php
会频繁产生版本冲突,可让团队成员分辨定义自己的路由文件,最后在 config.router.php
中整合这些路由文件,比如:
//config.router.a.php
return array(
'/' => '[module_dir_name]\controller\IndexController:someMethod'
)
//config.router.b.php
return array (
'/xyz' => '[module_dir_name]\controller\IndexController'
)
//config.router.php
$a = include __DIR__ . DIRECTORY_SEPARATOR . 'config.router.a.php';
$b = include __DIR__ . DIRECTORY_SEPARATOR . 'config.router.b.php';
$router = array(
'/mnu' => ['[module_dir_name]\controller\IndexController']
)
$router = array_merge($router, $a);
$router = array_merge($router, $b);
return $router;
1.3 注解
框架支持通过注解的方式配置路由,在使用注解前需要先在控制器中引入注解类 use hymie\annotation\RouterMapping;
注解定义的方法参考以下代码示例
以下示例中 SomeController 类只有默认方法 index 因此路由映射使用正则不会产生影响
use hymie\annotation\RouterMapping;
/**
* @RouterMapping(value="/(\w*)")
*/
class SomeController
{
public function index($name)
{
// handle path '/abc' '/def' /ghi
// $name = "abc" or "def" or "ghi"
}
}
如果类中其他方法也映射路由,那么这个类上的路由映射一般作为目录分割用,在类路由配置使用正则表达式的时候要细致考虑 URL结构
use hymie\annotation\RouterMapping;
/**
* @RouterMapping(value="/other")
*/
class SomeOtherController
{
public function index()
{
// handle path '/other'
}
/**
* @RouterMapping(value="/foo-(\d{1,3})")
*/
public function login($number)
{
// handle path '/other/foo-1" "/other/foo-123"
// $number = 1 or $number = 123
//could not handle '/ohter/foo-1234'
}
}
如果类的方法需要注解,那么类上的注解一般作为 URL 目录区分用,在这种情况下需要慎重使用正则表达式。
二、URL
2.1 URL 模式
支持两种 URL 模式,PATHINFO 和 QueryString,在 config.php
中的 url
部分进行配置。url
配置会影响到 \hymie\Url
类生成链接的方式。
注: nginx 需要进行配置才能支持 PATHINFO,请参考 服务器配置示例部分
注: 如果要生成 url_rewrite 的 url, 需要在配置文件的
url
部分设置url_rewrite
= true
2.2 生成 URL
页面中不能写死跳转到应用内的地址或者链接,因为修改 URL 模式后应用将无法正常工作,因此在需要跳转地址或者生成链接时需要使用 \hymie\Url
类,或者帮助函数 _U
以及 U
。
2.2.1 Url 类
Url 类是生成地址的工具类,它根据 config.php
中 $config['url']
的配置来动态生成 url 地址,比如以 简介 中的 example
项目为例。
-
生成短 URL
$url = new \hymie\Url('/a/b', ['a'=>1,'b'=>'2']); // or $url = new \hymie\Url('/a/b', 'a=1&b=2'); echo $url->getUrl()
- 如果
$config['url']['enable_query_string'] = true;
则输出/example/index.php?g=a.b&a=1&b=2
- 如果
$config['url']['enable_query_string'] = false;
则输出/example/index.php/a/b?a=1&b=2
- 如果
$config['url']['enable_query_string'] = false; $config['url']['rewrite_enabled'] = true;
则输出/example/a/b?a=1&b=2
- 如果
-
生成长 URL
$url = new \hymie\Url('/a/b', ['a'=>1,'b'=>'2']); // or $url = new \hymie\Url('/a/b', 'a=1&b=2'); echo $url->getUrl(false);
- 如果
$config['url']['enable_query_string'] = true;
则输出http://localhost/example/index.php?g=a.b&a=1&b=2
- 如果
$config['url']['enable_query_string'] = false;
则输出http://localhost/example/index.php/a/b?a=1&b=2
- 如果
$config['url']['enable_query_string'] = false; $config['url']['rewrite_enabled'] = true;
则输出http://localhost/example/a/b?a=1&b=2
- 如果
-
跳转到其他入口文件(仅
$config['url']['rewrite_enabled'] = false;
时有效$url = new \hymie\Url('/x/y', ['a'=>1,'b'=>'2'], 'index_other.php'); // or $url = new \hymie\Url('/x/y', 'a=1&b=2', 'index_other.php'); echo $url->getUrl()
- 如果
$config['url']['enable_query_string'] = true;
则输出/example/index_other.php?g=x.y&a=1&b=2
- 如果
$config['url']['enable_query_string'] = false;
则输出/example/index_other.php/x/y?a=1&b=2
- 如果
$config['url']['enable_query_string'] = false; $config['url']['rewrite_enabled'] = true;
则输出/example/x/y?a=1&b=2
- 如果
- 启用 pathinfo 以及 url_rewrite 时 当启动 pathinfo 和 url_rewrite 时,对于不同入口文件需要在 web 服务器上做路径映射配置,具体请参考 服务器配置示例
2.2.2 U
_U
R
函数
这两个函数是 hymie\Url
类的帮助函数
-
U
函数function U($path, $params = null, $script_name = '')
直接输出短地址,如果$path
是以http(s)
开头的则是站外地址。 -
_U
函数function _U($path, $params = null, $script_name = '')
返回短地址,如果$path
是以http(s)
开头的则是站外地址。 R
函数function R($to)
跳转到$to
地址,如果$to
是以http(s)
开头的则代表是站外地址。
2.3 上下文函数
context_path()
函数返回当前上下文,引用静态资源时可使用该函数。
2.4 静态资源
建议将静态资源统一放到 static
目录,或者其他名字的目录下,以便于统一管理,因为如果开启 pathinfo 和 url_rewrite 需要对 web 服务器做重写配置,静态资源统一放到单独目录下便于配置服务器重写规则。
三、过滤器
应用中可以定义多个过滤器,过滤器配置可参考 配置文件 章节。
过滤器按照定义顺序逐个执行,如果全部通过则执行控制器。
2.1 过滤器配置
如果模块目录下包含 config.filter.php
且应用程序使用了该模块, 则会自动加载此配置文件.配置文件中定义针对 URL
的过滤器配置, 配置使用 PHP PCRE 正则表达式.
'/admin/.*' => [
'class' => '\admin\filter\LoginFilter',
'exclude' => '/admin/login',
]
以上代码拦截所有 以 /admin/
开头的 URL
地址, 比如:
http://example.com/index.php?g=admin/index
http://example.com/index.php/admin/index
http://example.com/admin/index
(PATHINFO 并且开启 url_rewrite).
class 过滤器类
exclude 配置可以是数组也可以是正则表达式, 如果是数组,那么每个数组向均是正则表达式,代表此过滤器不拦截的 URL
地址规则.
过滤器按照定义的顺序执行
2.2 过滤器类
过滤器需要继承 \hymie\filter\Filter
类, 并实现 doFilter()
方法。
-
方法中可以使用
R($to)
方法跳转页面, 也可清理数据、设置环境参数等操作。 - 如果过滤器不跳转地址,那么如果通过则必须返回
true
代表通过并继续执行下一个过滤器,否则返回\hymie\Result
跳转到相应视图。
2.3 实现过滤器
<?php
namespace web\filter;
class SomeFilter extends \hymie\filter\Filter
{
public function doFilter()
{
$checkResult = doSomeBusinessCheck();
if ($checkResult == true) {
return true;
} else {
$data = ["error" => "err message", "data" => "somedata"]
return result()->addArray($data)->setView("error/filter_error");
}
}
}