ellipse/handlers-controller

Psr-15 请求处理器,使用 Psr-11 容器条目代理类方法

1.0.2 2018-03-19 15:53 UTC

This package is auto-updated.

Last update: 2024-08-26 00:37:22 UTC


README

此软件包提供了一个 Psr-15 请求处理器,该处理器使用 Psr-11 容器代理类方法。

要求 php >= 7.0

安装 composer require ellipse/handlers-controller

运行测试 ./vendor/bin/kahlan

使用控制器作为请求处理器

Ellipse\Handlers\ControllerRequestHandler 类接受 Psr\Container\ContainerInterface 的一个实现、一个容器 ID、一个方法名以及可选的请求属性名数组作为参数。它的 ->handle() 方法从容器中检索控制器类的实例,并调用具有给定名称的方法以返回一个响应。

控制器方法通过容器检索其类型提示参数的值来执行。与给定请求属性名匹配的请求属性值用于非类型提示参数,顺序与列表中的顺序相同。

当控制器方法有一个类型提示为 Psr\Http\Message\ServerRequestInterface 的参数时,使用请求处理器接收到的实际 Psr-7 请求。这意味着当中间件创建一个新的请求(因为 Psr-7 请求是不可变的)时,控制器方法将接收到这个新请求。

当从容器检索的控制器不是对象时,将抛出 Ellipse\Handlers\Exceptions\ContainedControllerTypeException

<?php

namespace App\Controllers;

use Psr\Http\Message\ServerRequestInterface;

use App\SomeService;
use App\SomeOtherService;

class SomeController
{
    public function __construct(SomeService $service)
    {
        //
    }

    public function index(SomeOtherService $service)
    {
        // return a Psr-7 response
    }

    public function show(SomeOtherService $service, $some_id)
    {
        // return a Psr-7 response
    }

    public function store(ServerRequestInterface $request)
    {
        // return a Psr-7 response
    }
}
<?php

namespace App;

use SomePsr11Container;

use Ellipse\Handlers\ControllerRequestHandler;

use App\Controllers\SomeController;

// Get some Psr-11 container.
$container = new SomePsr11Container;

// Register the controller in the container.
$container->set(SomeController::class, function ($container) {

    return new SomeController(new SomeService);

});

// Register some services in the container.
$container->set(SomeOtherService::class, function ($container) {

    return new SomeOtherService;

});

// Those request handlers are using the Psr-11 container, controller class names, methods and attributes.
$handler1 = new ControllerRequestHandler($container, SomeController::class, 'index');
$handler2 = new ControllerRequestHandler($container, SomeController::class, 'show', ['some_id']);
$handler3 = new ControllerRequestHandler($container, SomeController::class, 'store');

// The request handler ->handle() method proxy SomeController index method.
// The contained instance of SomeOtherService is passed to the method.
$response = $handler1->handle($request);

// Here the request handler ->handle() method proxy SomeController show method.
// The contained instance of SomeOtherService is passed to the method.
// The $some_id parameter will receive the request 'some_id' attribute value.
$response = $handler2->handle($request);

// Here the request handler ->handle() method proxy SomeController store method.
// The $request parameter will receive the actual Psr-7 request received by the request handler.
$response = $handler3->handle($request);

使用自动装配的示例

在容器中注册每个控制器类可能会很麻烦。以下是如何使用来自 ellipse/container-reflection 软件包的 Ellipse\Container\ReflectionContainer 类自动装配控制器实例的说明。

<?php

// Let controller classes implement some dummy interface specific to the application.

namespace App\Controllers;

class SomeController implements ControllerInterface
{
    // ...
}
<?php

namespace App;

use SomePsr11Container;

use Ellipse\Container\ReflectionContainer;
use Ellipse\Handlers\ControllerRequestHandler;

use App\Controllers\ControllerInterface;
use App\Controllers\SomeController;

// Get some Psr-11 container.
$container = new SomePsr11Container;

// Decorate the container with a reflection container.
// Specify the classes implementing ControllerInterface can be auto wired.
$reflection = new ReflectionContainer($container, [
    ControllerInterface::class,
]);

// Create a controller request handler using the reflection container and a controller class name.
$handler = new ControllerRequestHandler($reflection, SomeController::class, 'index');

// An instance of SomeController is built using auto wiring.
$response = $handler->handle($request);