Extending and Customizing

WellRESTed is designed with customization in mind. This section describes some common scenarios for customization, starting with using a handler that implements a different interface.

Custom Handlers and Middleware

Imagine you found a handler class from a third party that does exactly what you need. The only problem is that it implements a different interface.

Here’s the interface for the third-party handler:

interface OtherHandlerInterface
{
    /**
     * @param ServerRequestInterface $request
     * @return ResponseInterface
     */
    public function run(ResponseInterface $response);
}

Wrapping

One solution is to wrap an instance of this handler inside of a Psr\Http\Server\RequestHandlerInterface instance.

/**
 * Wraps an instance of OtherHandlerInterface
 */
class OtherHandlerWrapper implements RequestHandlerInterface
{
    private $handler;

    public function __construct(OtherHandlerInterface $handler)
    {
        $this->handler = $handler;
    }

    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        return $this->handler->run($request);
    }
}

Custom Dispatcher

Wrapping works well when you have one or two handlers implementing a third-party interface. If you want to integrate a lot of classes that implement a given third-party interface, you’re might consider customizing the dispatcher.

The dispatcher is an instance that unpacks your handlers and middleware and sends the request and response through it. A default dispatcher is created for you when you use your WellRESTed\Server.

If you need the ability to dispatch other types of middleware, you can create your own by implementing WellRESTed\Dispatching\DispatcherInterface. The easiest way to do this is to subclass WellRESTed\Dispatching\Dispatcher. Here’s an example that extends Dispatcher and adds support for OtherHandlerInterface:

/**
 * Dispatcher with support for OtherHandlerInterface
 */
class CustomDispatcher extends \WellRESTed\Dispatching\Dispatcher
{
    public function dispatch(
        $dispatchable,
        ServerRequestInterface $request,
        ResponseInterface $response,
        $next
    ) {
        try {
            // Use the dispatch method in the parent class first.
            $response = parent::dispatch($dispatchable, $request, $response, $next);
        } catch (\WellRESTed\Dispatching\DispatchException $e) {
            // If there's a problem, check if the handler or middleware
            // (the "dispatchable") implements OtherHandlerInterface.
            // Dispatch it if it does.
            if ($dispatchable instanceof OtherHandlerInterface) {
                $response = $dispatchable->run($request);
            } else {
                // Otherwise, re-throw the exception.
                throw $e;
            }
        }
        return $response;
    }
}

To use this dispatcher, create an instance implementing WellRESTed\Dispatching\DispatcherInterface and pass it to the server’s setDispatcher method.

$server = new WellRESTed\Server();
$server->setDispatcher(new MyApi\CustomDispatcher());

Warning

When you supply a custom Dispatcher, be sure to call Server::setDispatcher before you create any routers with Server::createRouter to allow the Server to pass you customer Dispatcher on to the newly created Router.