jerowork/route-attribute-provider

使用PHP8属性定义路由

0.7.0 2024-05-28 13:07 UTC

This package is auto-updated.

Last update: 2024-08-31 18:12:13 UTC


README

Build Status Coverage Status Quality Score Software License Packagist Version PHP Version

使用PHP8属性定义路由。

安装

通过Composer安装

$ composer require jerowork/route-attribute-provider

配置

为了使用路由属性,选择任何现有的框架实现或创建一个自定义的。

实例化RouteAttributeConfigurator在应用程序构建附近,例如在您的入口控制器中(或理想情况下注册到您的PSR-11容器中)。

基本配置

use Jerowork\RouteAttributeProvider\RouteAttributeConfigurator;

// ...

$routeConfigurator = new RouteAttributeConfigurator(
    new CustomRouteProvider($router)  // Implementation of your choice
);

$routeConfigurator
    ->addDirectory(sprintf('%s/src/Infrastructure/Api/Http/Action', __DIR__))
    ->configure();

// ...

扩展配置

use Jerowork\FileClassReflector\FileFinder\RegexIterator\RegexIteratorFileFinder;
use Jerowork\FileClassReflector\NikicParser\NikicParserClassReflectorFactory;
use Jerowork\RouteAttributeProvider\RouteAttributeConfigurator;
use Jerowork\RouteAttributeProvider\RouteLoader\ClassReflector\ClassReflectorRouteLoader;
use PhpParser\NodeTraverser;
use PhpParser\ParserFactory;
// ...

// All parts of the configurator can be replaced with a custom implementation
$routeConfigurator = new RouteAttributeConfigurator(
    new CustomRouteProvider($router), // Implementation of your choice
    new ClassReflectorRouteLoader(
        new NikicParserClassReflectorFactory(
            new RegexIteratorFileFinder(),
            (new ParserFactory())->create(ParserFactory::PREFER_PHP7),
            new NodeTraverser()
        )
    )
);

// Multiple directories can be defined
$routeConfigurator
    ->addDirectory(
        sprintf('%s/src/Infrastructure/Api/Http/Action', __DIR__),
        sprintf('%s/src/Other/Controller', __DIR__)
    )
    ->configure();

// ...

现有实现

或者查看packagist以获取其他实现。

自定义实现

使用RouteAttributeProviderInterface创建自定义实现。

一个(虚构的)自定义实现

use Jerowork\RouteAttributeProvider\Api\Route;
use Jerowork\RouteAttributeProvider\RouteAttributeProviderInterface;

final class CustomRouteProvider implements RouteAttributeProviderInterface
{
    private SomeRouter $router;
    
    public function __construct(SomeRouter $router)
    {
        $this->router = $router;
    }

    public function configure(string $className,string $methodName, Route $route) : void
    {
        // Register rule at your router
        $rule = $this->router->addRule(
            $route->getMethods(),
            $route->getPattern(),
            $className.':'.$methodName,
            $route->getName()
        );

        // Register optional middleware
        foreach ($route->getMiddleware() as $middleware) {
            $rule->addMiddleware($middleware);
        }
    }
}

缓存

默认情况下,路由属性缓存是禁用的。这对于开发环境来说是可以的。

然而,对于生产环境,您应该使用更高效的路线属性加载方式。因此,您可以使用任何PSR-16缓存实现。

use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\Cache\Psr16Cache;

// ...

// Enable route attribute caching with any PSR-16 implementation (e.g. symfony/cache)
$routeConfigurator->enableCache(new Psr16Cache(new ApcuAdapter()));

// ...

注意:也可以使用任何PSR-6缓存实现,通过使用Symfony的PSR-6到PSR-16适配器

用法

可以通过PHP8属性定义路由。

最小化示例

use Jerowork\RouteAttributeProvider\Api\Route;
use Psr\Http\Message\ResponseInterface as ServerRequest;
use Psr\Http\Message\ServerRequestInterface as Response;

final class RootAction
{
    #[Route('/root')]
    public function __invoke(ServerRequest $request, Response $response) : Response
    {
        return $response;
    }
}

扩展示例

use Jerowork\RouteAttributeProvider\Api\RequestMethod;
use Jerowork\RouteAttributeProvider\Api\Route;
use Psr\Http\Message\ResponseInterface as ServerRequest;
use Psr\Http\Message\ServerRequestInterface as Response;

final class RootAction
{
    #[Route('/root', method: RequestMethod::GET, name: 'root', middleware: SomeMiddleware::class)]
    public function __invoke(ServerRequest $request, Response $response) : Response
    {
        return $response;
    }
}

完整示例

use Jerowork\RouteAttributeProvider\Api\RequestMethod;
use Jerowork\RouteAttributeProvider\Api\Route;
use Psr\Http\Message\ResponseInterface as ServerRequest;
use Psr\Http\Message\ServerRequestInterface as Response;

final class RootAction
{
    #[Route('/root',
        method: [RequestMethod::GET, RequestMethod::POST],
        name: 'root',
        middleware: [
            SomeMiddleware::class,
            AnotherMiddleware::class,
        ],
        host: 'localhost',
        schemes: ['http', 'https'],
        httpPort: 8888,
        httpsPort: 9999,
        options: ['strategy' => 'something']
    )]
    #[Route('/second-route',
        method: RequestMethod::DELETE,
        name: 'second-route'
    )]
    public function __invoke(ServerRequest $request, Response $response) : Response
    {
        return $response;
    }
}