定制 kod/bootstrap-slim 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

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

kod/bootstrap-slim

Composer 安装命令:

composer require kod/bootstrap-slim

包简介

Library for bootstrapping a Slim based application.

README 文档

README

This package provides a library for bootstrapping Slim framework 4 application. (Release 1 is for Slim 3)

Purpose

  • Centralize the application's initialisation
  • Reuse existing configuration in unit tests
  • Create on the fly new customized configuration for unit tests
  • Reduce usage of require/include statements in favour of use statement

Installation

Add this package to require section of the composer.json

composer require kod/bootstrap-slim

Implementation in 3 steps

Bootstrap - step 1

On index.php for handling public requests.

<?php
use MyProject\Bootstrap;

// application configuration
$config = require('config.php');

 (new Bootstrap($config))
        ->addAppRoutes()
        ->addAppMiddlewares()
        ->run();

Of course, Bootstrap class does not provide any route or middleware except native Slim RoutingMiddleware and ErrorMiddleware. You need to extend it and declare your routes in Bootstrap::addAppRoutes() and middleware stack in Bootstrap::addAppMiddlewares() methods. It can be done easily by declaring class names like in example below.

Declare application routes and middleware stack

<?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
        );
    }
}

None of those classes exists yet. So, let's start with the most important. Let's create our route.

Routing - step 2

You have 2 options for creating routes. If you are a fun of OOP you can create a class containing your routes by extending RouteDefintions abstract class and declare your routes in __invoke($app) method of this class. As said above, you can but you are not obliged to. The MUST is to implement the __invoke($app) method in your class which receives Slim\App instance as a parameter. The instance of the class is executed like a function.

And here comes the 2nd option. You can declare your routes as Closure which gets Slim\App instance as a parameter. The 2nd approach is quite useful for unit tests if you need to create a route on the fly. But what am I saying? I'm getting obsolete. With php we can create anonymous classes! ¡Ay, caramba!

Anyway, just keep in mind that in both cases the Slim\App instance is passed as a parameter. That means you can organize your routes in groups and attach middleware to some route or group.

Route as a class:

<?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;
        });
    }
}

Application routes' declaration as a Closure

<?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;
               });
            }
        );
    }
}

Middleware - step 3

You can create a middleware in 2 ways: as a class or a closure. To create it as a class simply extend invokable Middleware abstract class, implement your business logic in it and trigger its execution in Middleware::__invoke( ServerRequestInterface $request,RequestHandlerInterface $handler) method.

Slim 4 middleware implements PSR-15 Middleware Interface which means that you do not have to use Middleware abstract class but write your own implementing the PSR-15 Middleware Interface. That'll do the job as well.

Either way, the application container will be pushed into the constructor of the middleware class by Slim\MiddlewareDispatcher.In Middleware derived classes the container will be stocked in $this->ci property.

To create a middleware as a closure simply respect the function signature.

Middleware as invokable class

<?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;
    }
}

Application middleware declaration

<?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;
           }
        );
    }
}

Route/Group middleware

Slim allows to attach a middleware to a route or a group of routes. This can be done in routes' definition like in example below.

<?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);
    }
}

Container

Slim 4 has a breaking change. It does not have container anymore. But no worry! This package provides an implementation of ContainerInterface built on top of Pimple\Container with same methods as in Slim 3. If your application relies on some other container implementation simply provide the instance of your container to Bootstrap. Another way to customize the container is to override Bootstrap::init method in your Bootstrap class and declare it in there.

<?php
use MyProject\Bootstrap;
use MyProject\MyContainer;

// application configuration
$config = require('config.php');
$container = new MyContainer($config);

(new Bootstrap($container))
        ->addAppRoutes()
        ->addAppMiddlewares()
        ->run();

Unit Testing

The keyword in unit testing is UNIT. Once your application is well organized and weakly coupled unit testing is like playing LEGO with your code. You can assemble routes and middleware, declare them on the fly as you wish.

<?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 dependency

Slim framework 4 now makes part of project dependencies due to quite sophisticated request/response forgery introduced with the latest version. To get rid of that dependency and rely on the slim version installed on your project you need to override Bootstrap::init method and use AppFactory and ServerRequestCreatorFactory coming with your project.

kod/bootstrap-slim 适用场景与选型建议

kod/bootstrap-slim 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 45 次下载、GitHub Stars 达 1, 最近一次更新时间为 2018 年 12 月 04 日, 在 PHP 生态内属于活跃度较高的组件。

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

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

围绕 kod/bootstrap-slim 我们能提供哪些服务?
定制开发 / 二次开发

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

BUG 修复 & 性能优化

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

项目外包 & 长期维护

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

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

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2018-12-04