pocket-framework / framework
一个尽量不干扰的简单PHP框架
Requires
- laminas/laminas-diactoros: ^2.9
- laminas/laminas-httphandlerrunner: ^2.1
- nikic/fast-route: ^1.3
- psr/container: ^1.0 || ^2.0
- psr/http-server-middleware: ^1.0
README
一个尽量不干扰的简单PHP框架
Pocket Framework是一个设计用来不干扰的简单PHP框架。使用普通的PHP对象编写代码,加入一些属性,你就可以开始使用了!
安装
使用composer进行安装
composer require pocket-framework/framework
要求
- PHP 8.1或更高版本
使用
Pocket Framework需要一个小的引导脚本才能运行,因为该框架需要一个HTTP分发器(包含nikic/fast-route
)以及一个PSR-11兼容的服务容器。我们建议使用php-di/php-di
。
// index.php <?php declare(strict_types=1); use DI\ContainerBuilder; use FastRoute\RouteCollector; use PocketFramework\Framework\Application; use PocketFramework\Framework\Router\RouteProcessor; session_start(); require_once __DIR__ . '/../vendor/autoload.php'; // Just pulls in a PHP-DI definition file, nothing specific to Pocket Framework $container = (new ContainerBuilder()) ->addDefinitions(require_once __DIR__ . '/../config/di.php') ->build(); $dispatcher = FastRoute\simpleDispatcher(function (RouteCollector $r) { // Set the folder your controllers/actions are stored in $processor = new RouteProcessor(realpath(__DIR__ . '/../src/Action'), "My\\WebApp\\Action\\"); $processor->addRoutes($r); }); $app = new Application($dispatcher, $container); $app->run();
配置
Pocket Framework目前没有太多配置,除了定义你的PSR-11服务容器(按库逐个定义)和告诉PocketFramework\Framework\Router\RouteProcessor
在哪里查找你的控制器和操作。否则,你可以通过PHP属性声明你的控制器(如果你使用的是模型-视图-控制器模式)或操作(如果你使用的是动作-领域-响应者模式)。
// Setting up the nikic/fast-route Dispatcher $dispatcher = FastRoute\simpleDispatcher(function (RouteCollector $r) { // Set the folder your controllers/actions are stored in $processor = new RouteProcessor(realpath(__DIR__ . '/../src/Action'), "My\\WebApp\\Action\\"); $processor->addRoutes($r); });
如果你有PSR-15中间件,你也可以将其添加到路由堆栈中。这些中间件可以帮助进行身份验证、记录或其他任何在路由分发之前需要执行的操作。
$application->addMiddleware(new My\WebApp\Middleware\CustomMiddleware());
声明路由
Pocket Framework允许你使用通用PHP对象上的PHP属性声明路由,可以使用模型-视图-控制器(MVC)模式或动作-领域-响应者(ADR)模式。你甚至可以混合使用!唯一的区别是属性的位置。
Pocket Framework提供了两个属性 - PocketFramework\Framework\Router\RouteGroup
和 PocketFramework\Framework\Router\RouteInfo
。RouteInfo
属性表示一个方法或类应该附加到特定的路由,并允许你定义路径、方法和任何所需的特定路由中间件。RouteGroup
用于定义包含多个共享相同基本URI的路由的类的基路由。
如果你使用的是ADR,其中一个类通常处理一个动作或路由,你可以在可调用的类上直接使用RouteInfo
来将其映射到路由。当访问该路由时,Pocker Framework将调用该类。
use PocketFramework\Framework\Router\RouteInfo; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; // Maps this invokable class to /example #[RouteInfo(route: '/example', methods: ['GET'])] class MyController { public function __invoke(ServerRequestInterface $request): ResponseInterface { return new JsonResponse(['status' => 1]); } }
如果你使用的是MVC,其中一个对象可能处理多个路由,你可以使用类方法上的RouteInfo
来将方法映射到路由。如果你结合使用RouteGroup
属性,类中的所有路由将共享一个共同的基本URI。
use PocketFramework\Framework\Router\RouteInfo; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; // Prepends /example to all routes inside this class #[RouteGroup(routeBase: '/example')] class MyController { // Maps this method to /example/ #[RouteInfo(route: '/', methods: ['GET'])] public function index(ServerRequestInterface $request): ResponseInterface { return new JsonResponse(['status' => 1]); } // Maps this method to /example/test #[RouteInfo(route: '/test', methods: ['GET'])] public function index(ServerRequestInterface $request): ResponseInterface { return new JsonResponse(['status' => 1]); } }
RouteGroup
和RouteInfo
都允许你在URL中添加动态片段。你可以在URL中添加{<identifier>:<regex>}
来指定要捕获和比较的值。此值将被传递到相关的路由以用于你的业务逻辑。请注意,无论正则表达式如何,该值都作为字符串传递到控制器中,因为URL本身就是一个字符串。
use PocketFramework\Framework\Router\RouteInfo; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; // Maps this invokable class to /user/<number> #[RouteInfo(route: '/user/{id:\d+}', methods: ['GET'])] class MyController { public function __invoke(ServerRequestInterface $request, string $id): ResponseInterface { return new JsonResponse(['status' => 1]); } }