Symfony RequestMatcher 详解
RequestMatcher 是 Symfony 中用于匹配 HTTP 请求的工具类,常用于访问控制、路由匹配、防火墙配置等场景。

基本用法
use Symfony\Component\HttpFoundation\RequestMatcher;
use Symfony\Component\HttpFoundation\Request;
// 创建匹配器
$matcher = new RequestMatcher();
// 匹配路径(支持正则)
$matcher->matchPath('/admin/*');
$matcher->matchPath('^/api/');
// 匹配主机名
$matcher->matchHost('example.com');
$matcher->matchHost('*.example.com');
// 匹配HTTP方法
$matcher->matchMethod('GET');
$matcher->matchMethod(['GET', 'POST']);
// 匹配IP地址
$matcher->matchIp('192.168.1.0/24');
$matcher->matchIp(['192.168.1.1', '10.0.0.0/8']);
// 匹配请求属性
$matcher->matchAttribute('_route', 'admin_dashboard');
// 执行匹配
$request = Request::create('/admin/users', 'GET');
$isMatched = $matcher->matches($request); // true/false
完整示例
use Symfony\Component\HttpFoundation\RequestMatcher;
// 复杂匹配规则
class AccessController
{
public function checkAccess(Request $request): bool
{
$matcher = new RequestMatcher();
// 设置多条规则(全部满足才匹配)
$matcher
->matchPath('^/api/')
->matchMethod('POST')
->matchHost('api.example.com')
->matchIp(['192.168.1.0/24', '10.0.0.0/8']);
return $matcher->matches($request);
}
public function isAdminArea(Request $request): bool
{
$matcher = new RequestMatcher();
$matcher->matchPath('^/admin');
return $matcher->matches($request);
}
}
在 Security 配置中使用
# config/packages/security.yaml
security:
access_control:
- { path: '^/admin', roles: ROLE_ADMIN }
- { path: '^/api', roles: ROLE_API_USER, methods: [POST] }
- { path: '^/public', roles: IS_AUTHENTICATED_ANONYMOUSLY }
// 在自定义防火墙中使用
use Symfony\Component\Security\Http\AccessMap;
use Symfony\Component\HttpFoundation\RequestMatcher;
$accessMap = new AccessMap();
$accessMap->add(
new RequestMatcher('^/admin'),
['ROLE_ADMIN']
);
$accessMap->add(
(new RequestMatcher())->matchPath('^/api')->matchMethod('POST'),
['ROLE_API_USER']
);
高级用法
组合多个匹配器
use Symfony\Component\HttpFoundation\ChainRequestMatcher;
// 创建多个匹配器
$pathMatcher = new RequestMatcher();
$pathMatcher->matchPath('^/api');
$methodMatcher = new RequestMatcher();
$methodMatcher->matchMethod('POST');
$hostMatcher = new RequestMatcher();
$hostMatcher->matchHost('api.example.com');
// 组合使用(全部满足)
$chainMatcher = new ChainRequestMatcher([
$pathMatcher,
$methodMatcher,
$hostMatcher
]);
$request = Request::create('/api/users', 'POST', [], [], [], ['HTTP_HOST' => 'api.example.com']);
$result = $chainMatcher->matches($request); // true
自定义匹配器
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\HttpFoundation\Request;
class CustomRequestMatcher implements RequestMatcherInterface
{
private array $allowedUserAgents;
public function __construct(array $allowedUserAgents)
{
$this->allowedUserAgents = $allowedUserAgents;
}
public function matches(Request $request): bool
{
$userAgent = $request->headers->get('User-Agent');
return in_array($userAgent, $this->allowedUserAgents);
}
}
// 使用
$customMatcher = new CustomRequestMatcher(['Symfony Browser', 'Chrome/91.0']);
$isMatched = $customMatcher->matches($request);
实际应用场景
// API版本控制
class ApiVersionMatcher
{
public function matchVersion(Request $request, string $version): bool
{
$matcher = new RequestMatcher();
$matcher->matchPath("^/api/v{$version}/");
return $matcher->matches($request);
}
}
// 多站点路由
class SiteRouter
{
public function matchSite(Request $request): string
{
$sites = [
'admin' => new RequestMatcher('^/admin'),
'api' => new RequestMatcher('^/api'),
'blog' => (new RequestMatcher())->matchPath('^/blog')->matchHost('blog.*'),
];
foreach ($sites as $name => $matcher) {
if ($matcher->matches($request)) {
return $name;
}
}
return 'default';
}
}
性能建议
- 缓存匹配结果:对于频繁检查的规则
- 简化正则表达式:避免过于复杂的模式
- 优先使用精确匹配:
/admin比^/admin/.*更快
class CachedRequestMatcher
{
private array $cache = [];
private RequestMatcher $matcher;
public function __construct()
{
$this->matcher = new RequestMatcher();
}
public function matches(Request $request): bool
{
$key = spl_object_id($request);
if (!isset($this->cache[$key])) {
$this->cache[$key] = $this->matcher->matches($request);
}
return $this->cache[$key];
}
}
注意事项
matchPath()支持正则表达式,但注意性能影响matchHost()支持通配符 ,但不支持正则matchIp()支持 CIDR 格式- 多个
match*方法调用是 AND 关系 - 新版本的 Symfony 推荐使用
RequestMatcherInterface的实现
这就是 Symfony RequestMatcher 的完整使用方法!它在安全控制、路由匹配等场景中非常实用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播