kod / bootstrap-slim
用于启动基于Slim框架的应用程序的库。
Requires
- pimple/pimple: ^3.2
- psr/container: ^1.0
- psr/http-message: ^1.0
- psr/http-server-handler: ^1.0
- slim/psr7: ^0.5.0
- slim/slim: ^4
Requires (Dev)
This package is auto-updated.
Last update: 2024-09-12 01:14:57 UTC
README
此包提供启动Slim框架4应用程序的库。(版本1是为Slim 3设计的)
目的
- 集中管理应用程序的初始化
- 在单元测试中重用现有配置
- 为单元测试动态创建新的定制配置
- 优先使用
use
语句,减少require
/include
语句的使用
安装
将此包添加到composer.json
文件的require
部分
composer require kod/bootstrap-slim
3步实现
启动 - 第1步
在index.php
中处理公开请求。
<?php use MyProject\Bootstrap; // application configuration $config = require('config.php'); (new Bootstrap($config)) ->addAppRoutes() ->addAppMiddlewares() ->run();
当然,Bootstrap
类不提供任何路由或中间件,除了本地的Slim RoutingMiddleware和ErrorMiddleware。您需要扩展它,并在Bootstrap::addAppRoutes()
中声明您的路由,以及在Bootstrap::addAppMiddlewares()
方法中声明中间件堆栈。这可以通过以下示例中的类名声明轻松完成。
声明应用程序路由和中间件堆栈
<?php namespace MyProject; use Kod\BootstrapSlim\Bootstrap as SlimBootstrap; class Bootstrap extends SlimBootstrap { public function addAppRoutes() { return $this->addRouteDefinitions( HomeRoutes::class, HelpRoutes::class ); } public function addAppMiddleware() { return $this->addMiddleware( ValidateResponse::class, SecurityHeaders::class, ValidateRequest::class ); } }
这些类目前还不存在。所以,让我们从最重要的开始。让我们创建我们的路由。
路由 - 第2步
您有两种创建路由的方式。如果您喜欢面向对象编程,您可以通过扩展RouteDefinitions
抽象类来创建一个包含您的路由的类,并在该类的__invoke($app)
方法中声明您的路由。如上所述,您可以这样做,但您不是必须这样做。必须实施的是在您的类中实现__invoke($app)
方法,该方法接收Slim\App
实例作为参数。类的实例可以作为函数执行。
接下来是第二种选择。您可以将路由声明为接收Slim\App
实例作为参数的闭包。第二种方法在需要动态创建路由的单元测试中非常有用。但我在说什么?我在过时。在PHP中,我们可以创建匿名类!¡Ay, caramba!
无论如何,请记住,在这两种情况下,都会将Slim\App
实例作为参数传递。这意味着您可以将路由分组,并将中间件附加到某些路由或路由组。
作为类的路由
<?php use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Kod\BootstrapSlim\RouteDefinitions; class HomesRoutes extends RouteDefinitions { public function __invoke($app) { $app->get('/', function (Request $request, Response $response, $args) { $response->getBody()->write('home page'); return $response; }); } }
作为闭包声明的应用程序路由
<?php namespace MyProject; use Kod\BootstrapSlim\Bootstrap as SlimBootstrap; use Slim\App; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use MyProject\Routes\HomesRoutes; class Bootstrap extends SlimBootstrap { public function addAppRoutes() { return $this->addRouteDefinitions( HomesRoutes::class, function(App $app){ $app->get('/', function (Request $request, Response $response, $args) { return $response; }); } ); } }
中间件 - 第3步
您可以通过两种方式创建中间件:作为一个类或一个闭包。要将其作为类创建,只需扩展可调用的Middleware
抽象类,在其中实现您的业务逻辑,并在Middleware::__invoke(ServerRequestInterface $request, RequestHandlerInterface $handler)
方法中触发其执行。
Slim 4中间件实现了PSR-15中间件接口,这意味着您不必使用Middleware
抽象类,而是编写自己的实现,实现PSR-15中间件接口。这也可以做到。
无论如何,应用程序容器将由Slim\MiddlewareDispatcher
推入中间件类的构造函数中。在Middleware
派生类中,容器将存储在$this->ci
属性中。
要作为闭包创建中间件,只需遵守函数签名。
作为可调用的类的中间件
<?php use Kod\BootstrapSlim\Middleware; use Psr\Http\{ Message\ResponseInterface, Message\ServerRequestInterface, }; use Psr\Http\Server\RequestHandlerInterface; /** * MiddlewareMock writes some content before and after content generation. */ class MyMiddleware extends Middleware { /** * @param ServerRequestInterface $request * @param RequestHandlerInterface $handler * @return ResponseInterface */ public function __invoke(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $container = $this->ci; // absolutely useless, just for the demo $response = $handler->handle($request); ... // some treatment here return $response; } }
应用程序中间件声明
<?php namespace MyProject; use Kod\BootstrapSlim\Bootstrap as SlimBootstrap; use Psr\Http\{ Message\ResponseInterface, Message\ServerRequestInterface, }; use Psr\Http\Server\RequestHandlerInterface; use MyProject\Middleware\MyMiddleware; class Bootstrap extends SlimBootstrap { public function addAppMiddleware() { return $this->addMiddleware( MyMiddleware::class, function (ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $container = $this; //bound by Slim\MiddlewareDispatcher $response = $handler->handle($request); ... // some treatment here return $response; } ); } }
路由/组中间件
Slim允许将中间件附加到路由或路由组。这可以在以下示例中的路由定义中完成。
<?php use Kod\BootstrapSlim\RouteDefinitions; use Slim\Psr7\{Request, Response}; use Slim\Interfaces\RouteCollectorProxyInterface; use MyProject\Middleware\MyMiddleware; class BillingRoutes extends RouteDefinitions { /** * @param App $app */ public function __invoke($app) { $app->group('/billing', function (RouteCollectorProxyInterface $group) { $group->get('/', function (Request $request, $response, $args) { // Route for /billing ... // some treatment return $response; }); $group->get('/invoice/{id:[0-9]+}', function (Request $request, Response $response, $args) { // Route for /invoice/{id:[0-9]+} ... // some treatment return $response; }); })->add(MyMiddleware::class); } }
容器
Slim 4 引入了一个重大变更。它不再包含容器。但别担心!此包提供了一个基于 Pimple\Container
的 ContainerInterface
实现,其方法与 Slim 3 相同。如果你的应用程序依赖于其他容器实现,只需将你的容器实例提供给 Bootstrap。另一种自定义容器的办法是在你的 Bootstrap 类中覆盖 Bootstrap::init
方法,并在其中声明它。
<?php use MyProject\Bootstrap; use MyProject\MyContainer; // application configuration $config = require('config.php'); $container = new MyContainer($config); (new Bootstrap($container)) ->addAppRoutes() ->addAppMiddlewares() ->run();
单元测试
单元测试中的关键字是 UNIT。一旦你的应用程序组织良好且松耦合,单元测试就像用你的代码玩积木一样。你可以组装路由和中间件,按需声明它们。
<?php use MyProject\{MyBootstrap, MyRoute}; use Kod\BootstrapSlim\Utils; class MyRouteTest extends TestCase { // test configuration public static $config = [ 'settings' => ['price' => 100] ]; public function testMyRouteWithoutAppMiddleware() { // Prepare environment for the request Utils::setEnv([ 'REQUEST_METHOD' => 'GET', 'REQUEST_URI' => '/', ]); // Process the request $response = (new MyBootstrap(static::$config)) ->addRouteDefinitions(MyRoute::class) ->run(true); $content = (string)$response->getBody(); // MyRoute class is supposed to return the price from settings $this->assertContains(100, $content); } public function testMyRouteWithAppMiddleware() { // Prepare environment for the request Utils::setEnv([ 'REQUEST_METHOD' => 'GET', 'REQUEST_URI' => '/', ]); // Process the request $response = (new MyBootstrap(static::$config)) ->addAppMiddleware() // <- declare application middleware ->addRouteDefinitions(MyRoute::class) ->run(true); $content = (string)$response->getBody(); // MyRoute class is supposed to return the price from settings $this->assertContains(100, $content); } }
Slim 依赖
由于最新版本引入了相当复杂的请求/响应伪造,Slim 框架 4 现在成为项目依赖的一部分。要摆脱这个依赖,并依赖于你的项目上安装的 slim 版本,你需要覆盖 Bootstrap::init
方法,并使用与你的项目一起提供的 AppFactory
和 ServerRequestCreatorFactory
。