Update documentation
This commit is contained in:
parent
45379ab241
commit
fa6fb124ad
|
|
@ -3,7 +3,7 @@ Dependency Injection
|
||||||
|
|
||||||
WellRESTed strives to play nicely with other code and not force developers into using any specific libraries or frameworks. As such, WellRESTed does not provide a dependency injection container, nor does it require you to use a specific container (or any).
|
WellRESTed strives to play nicely with other code and not force developers into using any specific libraries or frameworks. As such, WellRESTed does not provide a dependency injection container, nor does it require you to use a specific container (or any).
|
||||||
|
|
||||||
This section describes a handful of ways of making the dependency container of your choice available to middleware with WellRESTed.
|
This section describes a handful of ways of making dependencies available to middleware.
|
||||||
|
|
||||||
Request Attribute
|
Request Attribute
|
||||||
^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
@ -28,84 +28,75 @@ When the server dispatches middleware, the middleware will be able to read the c
|
||||||
// It's a super cool dependency container!
|
// It's a super cool dependency container!
|
||||||
}
|
}
|
||||||
|
|
||||||
Callables
|
.. note::
|
||||||
^^^^^^^^^
|
|
||||||
|
|
||||||
Another approach is to use callables that return ``MiddlewareInterface`` instances when you assign middleware. This approach provides an opportunity to pass the container into the middleware's constructor.
|
This approach is technically more of a `service locator`_ pattern. It's easy to implement, and it allows you the most flexibility in how you assign middleware.
|
||||||
|
|
||||||
|
It has some drawbacks as well, though. For example, your middleware is now dependent on your container, and describing which items needs to be **in** the container provides its own challenge.
|
||||||
|
|
||||||
|
If your interested in a truer dependency injection approach, read on to the next section where we look at registering middleware factories.
|
||||||
|
|
||||||
|
Middleware Factories
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Another approach is to use a factory function that returns middleware, usually in the form of a ``MiddlewareInterface`` instance. This approach provides the opportunity to pass dependencies to your middleware's constructor, while still delaying instantiation until the middleware is used.
|
||||||
|
|
||||||
|
Imagine a middleware ``FooHandler`` that depends on a ``BarInterface``, and ``BazInterface``.
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
Class CatHandler implements WellRESTed\MiddlewareInterface
|
Class FooHandler implements WellRESTed\MiddlewareInterface
|
||||||
{
|
{
|
||||||
private $container;
|
private $bar;
|
||||||
|
private $baz;
|
||||||
|
|
||||||
public function __construct($container)
|
public function __construct(BarInterface $bar, BazInterface $bar)
|
||||||
{
|
{
|
||||||
$this->container = $container;
|
$this->bar = $bar;
|
||||||
|
$this->baz = $baz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next);
|
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next);
|
||||||
{
|
{
|
||||||
// Do something with the $this->container, and make a response.
|
// Do something with the bar and baz and update the response.
|
||||||
// ...
|
// ...
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
When you add the middleware to the server or register it with a router, use a callable that passes container into the constructor.
|
When you add the middleware to the server or register it with a router, you can use a callable that passes appropriate instances into the constructor.
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
$container = new MySuperCoolDependencyContainer();
|
// Assume $bar and $baz exist in this scope.
|
||||||
|
$fooHandlerFactory = function () use ($bar, $bar) {
|
||||||
$catHandler = function () use ($container) {
|
return new FooHandler($bar, $baz);
|
||||||
return new CatHandler($container);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$server = new Server();
|
$server = new Server();
|
||||||
$server->add(
|
$server->add(
|
||||||
$server->createRoute()
|
$server->createRoute()
|
||||||
->register("GET", "/cats/{cat}", $catHandler)
|
->register("GET", "/foo/{id}", $fooHandlerFactory)
|
||||||
);
|
);
|
||||||
$server->respond();
|
$server->respond();
|
||||||
|
|
||||||
For extra fun, store the callable that provides the handler in the container. Here's an example using Pimple_).
|
You can combine this approach with a dependency container. Here's an example using Pimple_).
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
$c = new Pimple\Container();
|
$c = new Pimple\Container();
|
||||||
$c["catHandler"] = $c->protect(function () use ($c) {
|
$c["bar"] = /* Return a BarInterface */
|
||||||
return new CatHandler($c);
|
$c["baz"] = /* Return a BazInterface */
|
||||||
|
$c["fooHandler"] = $c->protect(function () use ($c) {
|
||||||
|
return new FooHandler($c["bar"], $c["baz"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
$server = new Server();
|
$server = new Server();
|
||||||
$server->add(
|
$server->add(
|
||||||
$server->createRoute()
|
$server->createRoute()
|
||||||
->register("GET", "/cats/{cat}", $c["catHandler"])
|
->register("GET", "/foo/{id}", $c["fooHandler"])
|
||||||
);
|
|
||||||
$server->respond();
|
|
||||||
|
|
||||||
Combined
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
Of course these two approaches are not mutually exclusive. You can even obtain your server from the container as well, for good measure.
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
$c = new Pimple\Container();
|
|
||||||
$c["server"] = function ($c) {
|
|
||||||
return new Server(["container" => $c);
|
|
||||||
};
|
|
||||||
$c["catHandler"] = $c->protect(function () use ($c) {
|
|
||||||
return new CatHandler($c);
|
|
||||||
});
|
|
||||||
|
|
||||||
$server = $c["server"];
|
|
||||||
$server->add(
|
|
||||||
$server->createRoute()
|
|
||||||
->register("GET", "/cats/{cat}", $c["catHandler"])
|
|
||||||
);
|
);
|
||||||
$server->respond();
|
$server->respond();
|
||||||
|
|
||||||
.. _Pimple: http://pimple.sensiolabs.org
|
.. _Pimple: http://pimple.sensiolabs.org
|
||||||
|
.. _service locator: https://en.wikipedia.org/wiki/Service_locator_pattern
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Extending and Customizing
|
Extending and Customizing
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
WellRESTed is designed with customization in mind. This section will describe some common scenarios for customization, starting with using middleware that implements a different interface.
|
WellRESTed is designed with customization in mind. This section describes some common scenarios for customization, starting with using middleware that implements a different interface.
|
||||||
|
|
||||||
Custom Middleware
|
Custom Middleware
|
||||||
-----------------
|
-----------------
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ Middleware can be a callable (as in the `Getting Started`_) or an implementation
|
||||||
Using Middleware
|
Using Middleware
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Methods that accept middleware (e.g., ``Server::add``, ``Router::register``) allow you to provide middleware in a number of ways. For example, when you can provide a callable, a string containing a class name, an instance, or even an array containing a sequence of middleware.
|
Methods that accept middleware (e.g., ``Server::add``, ``Router::register``) allow you to provide middleware in a number of ways. For example, you can provide a string containing a class name, a middleware callable, a factory callable, or even an array containing a sequence of middleware.
|
||||||
|
|
||||||
Fully Qualified Class Name (FQCN)
|
Fully Qualified Class Name (FQCN)
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
@ -93,8 +93,8 @@ Assume your Web service has an autoloadable class named ``Webservice\Widgets\Wid
|
||||||
|
|
||||||
The class is not loaded, and no instances are created, until the route is matched and dispatched. Even for a router with 100 routes, no middleware registered by string name is loaded, except for the one that matches the request.
|
The class is not loaded, and no instances are created, until the route is matched and dispatched. Even for a router with 100 routes, no middleware registered by string name is loaded, except for the one that matches the request.
|
||||||
|
|
||||||
Callable Provider
|
Factory Callable
|
||||||
-----------------
|
----------------
|
||||||
|
|
||||||
You can also use a callable to instantiate and return a ``MiddlewareInterface`` instance or middleware callable.
|
You can also use a callable to instantiate and return a ``MiddlewareInterface`` instance or middleware callable.
|
||||||
|
|
||||||
|
|
@ -104,14 +104,14 @@ You can also use a callable to instantiate and return a ``MiddlewareInterface``
|
||||||
return new \Webservice\Widgets\WidgetHandler();
|
return new \Webservice\Widgets\WidgetHandler();
|
||||||
});
|
});
|
||||||
|
|
||||||
This still delays instantiation, but gives you some added flexibility. For example, you could define middleware that receives some configuration upon construction.
|
This still delays instantiation, but gives you some added flexibility. For example, you could define middleware that receives some dependencies upon construction.
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
$container = new MySuperCoolDependencyContainer();
|
$container = new MySuperCoolDependencyContainer();
|
||||||
|
|
||||||
$router->add("GET,PUT,DELETE", "/widgets/{id}", function () use ($container) {
|
$router->add("GET,PUT,DELETE", "/widgets/{id}", function () use ($container) {
|
||||||
return new \Webservice\Widgets\WidgetHandler($container);
|
return new \Webservice\Widgets\WidgetHandler($container["foo"], $container["baz"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
This is one approach to `dependency injection`_.
|
This is one approach to `dependency injection`_.
|
||||||
|
|
@ -130,10 +130,7 @@ Use a middleware callable directly.
|
||||||
return $next($request, $response);
|
return $next($request, $response);
|
||||||
});
|
});
|
||||||
|
|
||||||
Instance
|
Because ``WellRESTed\MiddlewareInterface`` has an ``__invoke`` method, implementing instances are also middleware callables. Assuming ``WidgetHandler`` implements ``MiddelewareInterface``, you can do this:
|
||||||
--------
|
|
||||||
|
|
||||||
You can also provide pass an instance directly as middleware.
|
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
|
|
@ -141,7 +138,7 @@ You can also provide pass an instance directly as middleware.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
This is simple, but has a significant disadvantage over the other options because each middleware used this way will be loaded and instantiated, even though only one middleware will actually be used for a given request-response cycle. You may find this approach useful for testing, but avoid if for production code.
|
This is simple, but has a significant disadvantage over the other options because each middleware used this way will be loaded and instantiated, even if it's not needed for a given request-response cycle. You may find this approach useful for testing, but avoid if for production code.
|
||||||
|
|
||||||
Array
|
Array
|
||||||
-----
|
-----
|
||||||
|
|
@ -200,14 +197,17 @@ We can add authorization for just the ``/widgets/{id}`` endpoint like this:
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
$router->register("GET,PUT,DELETE", "/widgets/{id}", [
|
$server = new \WellRESTed\Server();
|
||||||
|
$server->add($server->createRouter()
|
||||||
|
->register("GET,PUT,DELETE", "/widgets/{id}", [
|
||||||
'Webservice\Authorization',
|
'Webservice\Authorization',
|
||||||
'Webservice\Widgets\WidgetHandler'
|
'Webservice\Widgets\WidgetHandler'
|
||||||
]);
|
])
|
||||||
|
->respond();
|
||||||
|
|
||||||
Or, if you wanted to use the authorization for the entire service, you can add it to the ``Server`` in front of the ``Router``.
|
Or, if you wanted to use the authorization for the entire service, you can add it to the ``Server`` in front of the ``Router``.
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
$server = new \WellRESTed\Server();
|
$server = new \WellRESTed\Server();
|
||||||
$server
|
$server
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue