preflow/routing
Composer 安装命令:
composer require preflow/routing
包简介
Preflow routing — file-based and attribute-based hybrid router
README 文档
README
Hybrid file-based + attribute-based router for Preflow. Implements RouterInterface from preflow/core.
Installation
composer require preflow/routing
Requires PHP 8.4+.
What's included
| Component | Description |
|---|---|
FileRouteScanner |
Maps app/pages/ directory structure to Component routes |
AttributeRouteScanner |
Scans PHP classes for #[Route], #[Get], #[Post], etc. |
Router |
Combines both scanners, implements RouterInterface |
RouteMatcher |
Matches requests with priority: static > dynamic > catch-all |
RouteCompiler |
Caches the route collection to a PHP file for production |
File-based routing
Files in the pages directory map directly to URLs. The scanner handles three file conventions:
| File | URL pattern |
|---|---|
index.twig |
/ (or parent directory path) |
about.twig |
/about |
[slug].twig |
/{slug} — dynamic segment |
[...path].twig |
/{path} — catch-all (matches slashes too) |
_layout.twig |
excluded (underscore prefix) |
Example structure:
app/pages/
index.twig → GET /
about.twig → GET /about
blog/
index.twig → GET /blog
[slug].twig → GET /blog/{slug}
docs/
[...path].twig → GET /docs/{path} (catches /docs/a/b/c)
_layout.twig → (ignored)
File routes resolve to RouteMode::Component — the handler value is the relative template path (e.g. blog/[slug].twig).
Attribute-based routing
Controllers use #[Route] on the class for a path prefix, then HTTP method attributes on methods. These resolve to RouteMode::Action with the handler ClassName@methodName.
use Preflow\Routing\Attributes\Delete; use Preflow\Routing\Attributes\Get; use Preflow\Routing\Attributes\Middleware; use Preflow\Routing\Attributes\Post; use Preflow\Routing\Attributes\Put; use Preflow\Routing\Attributes\Route; #[Route('/api/posts')] #[Middleware(ApiAuthMiddleware::class)] final class PostController { #[Get('/')] public function index(): ResponseInterface { /* ... */ } #[Get('/{id}')] public function show(): ResponseInterface { /* ... */ } #[Post('/')] public function create(): ResponseInterface { /* ... */ } #[Put('/{id}')] #[Middleware(OwnerMiddleware::class)] // stacks on top of class middleware public function update(): ResponseInterface { /* ... */ } #[Delete('/{id}')] public function destroy(): ResponseInterface { /* ... */ } }
Method paths are appended to the class prefix: #[Get('/{id}')] on #[Route('/api/posts')] becomes /api/posts/{id}. A method path of '/' resolves to the prefix alone.
#[Middleware] is repeatable on both class and method. Method middleware merges on top of class middleware.
Catch-all params in attribute routes
Append ... inside the braces to create a catch-all segment that matches slashes. Useful for nested path parameters in controllers.
#[Route('/files')] final class FileController { #[Get('/{path...}')] public function show(ServerRequestInterface $request): ResponseInterface { $path = $request->getAttribute('path'); // e.g. 'images/2026/photo.jpg' // ... } }
{path...} compiles to a .+ regex, matching one or more characters including /.
Router setup
use Preflow\Routing\Router; $router = new Router( pagesDir: __DIR__ . '/app/pages', // file-based routes (optional) controllers: [PostController::class], // attribute-based routes (optional) cachePath: __DIR__ . '/storage/routes.php', // null = no cache ); // Pass to Application $app->setRouter($router);
Either pagesDir or controllers (or both) can be omitted. When cachePath is set and the cache file exists, the scanner is bypassed entirely.
Route cache (production)
use Preflow\Routing\RouteCompiler; $compiler = new RouteCompiler(); // Generate cache $compiler->compile($router->getCollection(), __DIR__ . '/storage/routes.php'); // Invalidate $compiler->clear(__DIR__ . '/storage/routes.php');
The compiled file is a plain PHP return statement — no eval, OPcache-friendly.
Matching priority
For a given HTTP method, RouteMatcher tests routes in three passes:
- Static — exact string match, no parameters
- Dynamic — has
{param}segments, matched by regex - Catch-all — has
{...param}, matches across slashes
The first match wins. Throws NotFoundHttpException if nothing matches.
preflow/routing 适用场景与选型建议
preflow/routing 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 44 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 04 月 10 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 preflow/routing 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 preflow/routing 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
统计信息
- 总下载量: 44
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 25
- 依赖项目数: 3
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-04-10