appertly/ducts

适用于 Hack/HHVM 的 PSR-7 兼容中间件分发器

安装: 161

依赖项: 1

建议者: 0

安全: 0

星标: 1

关注者: 2

分支: 0

开放问题: 0

语言:Hack

0.1.0 2016-05-26 20:16 UTC

This package is not auto-updated.

Last update: 2024-09-14 18:53:10 UTC


README

适用于 Hack/HHVM 的 PSR-7 兼容中间件分发器。

这与 ConnectRelayStratigilityMiddleman 等类似,但严格遵循 Hack。

Packagist Build Status

安装

您可以使用 Composer 安装此库

$ composer require appertly/ducts
  • 此项目的 master 分支(版本 0.x)需要 HHVM 3.12,没有依赖项。

兼容性

此库的版本将遵循 语义版本控制

我们的代码旨在遵循 PSR-1PSR-2PSR-4。如果您发现任何与标准兼容性相关的问题,请发送 pull request!

层和分发

这里的想法是您提供一系列函数,这些函数

  1. 接受一个请求、一个响应和一个下一个函数
  2. 可能修改请求和响应
  3. 可能调用下一个函数,该函数返回一个响应
  4. 可能修改返回的响应
  5. 返回响应
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

function foobar(Request $req, Response $res, (function (Request,Response): Response) $next): Response
{
    // 2. possibly modify the request and response
    // 3. invoke next
    $res = $next($req, $res);
    // 4. possibly modify response
    // 5.
    return $res;
}

层最终会这样交互

  • → 第一层
    • → 第二层
      • → 第三层
      • ← 第三层
    • ← 第二层
  • ← 第一层

分发请求

use Ducts\Runner;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

/**
 * @var \Psr\Http\Message\ServerRequestInterface $request The PSR-7 HTTP request
 * @var \Psr\Http\Message\ResponseInterface $response The PSR-7 HTTP response
 */

// any Traversable will do. Use an array, Vector, etc.
$runner = new Runner([
    // you can use closures
    function(Request $req, Response $res, (function (Request,Response): Response) $next): Response {
        $req = $req->withAttribute('foo', 'bar');
        return $next($req, $res);
    },
    // or lambdas
    ($req, $res, $next) ==> $next($req, $res)->withHeader('X-Ducts', 'Yes')
    // or objects with an __invoke method
    new MyInvokableThing(),
    // or Hack-style callables
    fun('myLayer'),
    class_meth('MyLayer', 'staticMethod'),
    inst_meth($myObject, 'layer')
]);

$response = $runner->run($request, $response);

// Runner::run can be called multiple times if needed
$anotherResponse = $runner->run($request, $response);

如果您想查找层可调用函数,也可以使用 ResolvingRunner

// a function to look up names
$resolver = function(mixed $name): (function (Request,Response,(function(Request,Response): Response)): Response) {
    // look up your callable thing in a dependency injection container
    $container = MyClass::getSomeContainer();
    return $container->get($name);
};

// Items in this traversable can be a combination of functions or items to resolve
$runner = new ResolvingRunner([
    ($req, $res, $next) ==> $next($req, $res)->withHeader('X-Ducts', 'Yes'),
    'MyClassName',
    'AnotherClass'
], $resolver);

将 Runner 作为层使用

您可以通过调用 $runner->layer()Runner 用作层!例如,您将 Runner$bar 声明为 Runner 的第二层,其中 $foo 有三个层。如果 $bar 有三个层,它将像这样参与 $foo

  • $foo 层 1
    • $bar 层 1
      • $bar 层 2
        • $bar 层 3
          • $foo 层 3
          • $foo 层 3
        • $bar 层 3
      • $bar 层 2
    • $bar 层 1
  • $foo 层 1