mitsuki/router 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

mitsuki/router

Composer 安装命令:

composer require mitsuki/router

包简介

A lightweight and high-performance PHP router for the Mitsuki framework, powered by Symfony Routing components.

README 文档

README

Mitsuki is a modern HTTP routing engine for PHP, powered by Symfony Routing/HttpKernel and PHP 8 attributes. It provides:

  • Automatic controller discovery
  • Attribute-based routing (#[Controller], #[Route])
  • PSR-11 container integration
  • HttpKernel-compatible controller resolution
  • Compiled routes caching

Installation

composer require mitsuki/router

The router relies on Symfony Routing, HttpFoundation, HttpKernel, Filesystem, and a PSR-11 container.

Core Concepts

Attributes

  • #[Controller('prefix')] on classes
  • #[Route('name', 'path', methods)] on methods
use Mitsuki\Attributes\Controller;
use Mitsuki\Attributes\Route;
use Mitsuki\Controller\BaseController;
use Mitsuki\Http\Responses\JsonResponse;
use Mitsuki\Http\Request;

#[Controller('posts')]
class PostController extends BaseController
{
    #[Route('posts.index', '', ['GET'])]
    public function index(): JsonResponse
    {
        return $this->json(['data' => ['post 1', 'post 2', 'post 3']]);
    }

    #[Route('posts.store', '', ['POST'])]
    public function store(Request $request): JsonResponse
    {
        return $this->json([
            'title' => $request->request->get('title'),
        ]);
    }

    #[Route('posts.show', '{id}', ['GET'])]
    public function show(int $id): JsonResponse
    {
        return $this->json(['data' => 'post 1']);
    }

    #[Route('posts.update', '{id}', ['PUT'])]
    public function update(Request $request, int $id): JsonResponse
    {
        return $this->json(['id' => $id]);
    }

    #[Route('posts.destroy', '{id}', ['DELETE'])]
    public function destroy(int $id): JsonResponse
    {
        return $this->json([], status: 204);
    }
}

Architecture

Router Class

Namespace: Mitsuki\Hermite\Router

Responsibilities:

  • Load routes from compiled cache or controller scanning
  • Build Symfony RouteCollection
  • Delegate matching to UrlMatcher
  • Resolve HttpKernel-compatible controller callable
public function __construct(
    private RouteCollection    $routeCollection,
    private RequestContext     $requestContext,
    private ContainerInterface $container,
    private ControllerResolver $controllerResolver,
    string                     $cacheDir
)

Workflow

  1. load()

    • If cache_routes.php exists → load routes from cache
    • Otherwise → use ControllerResolver to discover controllers
    • Analyze attributes, build routes, write cache
  2. getCallable(Request $request)

    • Updates RequestContext::setMethod()
    • Uses UrlMatcher to match URL + method
    • Binds route parameters to request attributes
    • Fetches controller instance via container
    • Returns [instance, 'method'] for HttpKernel

Path Concatenation

In getRoutesFromControllers():

  • Class prefix: #[Controller('posts')]
  • Method path: #[Route('posts.show', '{id}', ['GET'])]
  • Normalized result: /posts/{id}

Normalization:

  • Removes multiple /
  • Strips trailing /
  • Falls back to / if empty

Container Integration

Example with PHP-DI:

use Mitsuki\Hermite\Router;
use Mitsuki\Controller\Resolvers\ControllerResolver;
use Psr\Container\ContainerInterface;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\EventDispatcher\EventDispatcher;

return [
    'project.root' => dirname(__DIR__) . '/src',
    'cache.dir'    => dirname(__DIR__) . '/var/caches',

    ControllerResolver::class => fn($c) => 
        new ControllerResolver($c->get('project.root')),

    Router::class => function (ContainerInterface $c) {
        $router = new Router(
            $c->get(RouteCollection::class),
            $c->get(RequestContext::class),
            $c,
            $c->get(ControllerResolver::class),
            $c->get('cache.dir')
        );

        $controllers = $c->has('controllers') ? $c->get('controllers') : [];
        $router->load($controllers);

        return $router;
    },

    ControllerResolverInterface::class => fn($c) => new class($c->get(Router::class)) implements ControllerResolverInterface {
        public function __construct(private Router $router) {}
        public function getController(Request $request): callable|false
        {
            return $this->router->getCallable($request);
        }
    },

    HttpKernelInterface::class => function (ContainerInterface $c) {
        $argumentResolver = new ArgumentResolver(
            null,
            [
                new RequestAttributeValueResolver(),
                new RequestValueResolver(),
                new DefaultValueResolver(),
            ]
        );

        return new HttpKernel(
            new EventDispatcher(),
            $c->get(ControllerResolverInterface::class),
            new RequestStack(),
            $argumentResolver
        );
    },

    RequestContext::class => \DI\create(RequestContext::class),
    RouteCollection::class => \DI\create(RouteCollection::class),
];

Request Lifecycle

HTTP Request
   ↓
HttpKernel::handle()
   ↓
Router::getCallable()
   ↓
[ControllerInstance, method]
   ↓
ArgumentResolver (Request, attributes, defaults)
   ↓
Controller executed
   ↓
JsonResponse / Response

Usage Example

use Mitsuki\Http\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;

$kernel = $container->get(HttpKernelInterface::class);

$request  = Request::create('/posts', 'GET');
$response = $kernel->handle($request);

echo $response->getStatusCode();  // 200
echo $response->getContent();     // JSON data

Testing

Tested with PestPHP (95%+ coverage).

Integration tests:

test('GET /posts returns index with paginated data - E2E', function () {
    $request  = Request::create('/posts', 'GET');
    $response = $this->app->get(HttpKernelInterface::class)->handle($request);
    
    $data = json_decode($response->getContent(), true);
    
    expect($response->getStatusCode())->toBe(200)
        ->and($data['data'])->toHaveCount(3);
});

test('returns 404 Not Found for unknown routes', function () {
    $request = Request::create('/unknown', 'GET');
    
    expect(fn() => $this->app->get(HttpKernelInterface::class)->handle($request))
        ->toThrow(NotFoundHttpException::class);
});

Run tests with coverage:

XDEBUG_MODE=coverage ./vendor/bin/pest --coverage --coverage-html coverage-report

Best Practices

  • Always define unique route names in #[Route]
  • Use consistent prefixes via #[Controller('prefix')]
  • Write tests for each CRUD endpoint
  • Enable route caching in production for optimal performance

Roadmap

  • Route-specific middleware support
  • Configurable route groups (auth, API, etc.)
  • URL generation from route names
  • Request validation & DTO integration

📄 License

This project is licensed under the MIT License.

Maintained by Zgenius Matondo GitHub: https://github.com/zgeniuscoders

mitsuki/router 适用场景与选型建议

mitsuki/router 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 4 次下载、GitHub Stars 达 1, 最近一次更新时间为 2026 年 02 月 20 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「routing」 「mvc」 「router」 「attributes」 「micro-framework」 「http-kernel」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 mitsuki/router 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 mitsuki/router 我们能提供哪些服务?
定制开发 / 二次开发

基于 mitsuki/router 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 4
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 27
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-02-20