Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Commit 69eadac

Browse files
committed
Documentation polishing
- [X] What is PSR-7? - [X] What is middleware? - [X] What can you build with Expressive? - [X] Features of Expressive - Routing - path-based - HTTP method constraints (405 responses built-in) - abstractions - container-interop - lazy-loading routed middleware - lazy-loading *piped* middleware - Error handling - basic 404 and general errors - templated error pages - whoops for development - Templating - abstracted - namespaced templates - layouts can be assumed - [X] Routing - [X] Detail how to fetch the matched attributes! - [X] Show simplified router factories when showing containers. Most of the routers do not *need* a factory, unless the user wants to provide additional configuration. As such, invokables or closures that return the instance will suffice in most cases. Have separate sections on *advanced* factories. - [X] Emitters and the EmitterStack - [X] Use case examples - Make them follow the guidelines from the various container examples with regards to configuration/service definition location. - [X] Search for "zend-expressive" at the start of sentences, and replace with "Expressive".
1 parent 6323dbf commit 69eadac

File tree

19 files changed

+564
-166
lines changed

19 files changed

+564
-166
lines changed

doc/book/application.md

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ that composes:
1414

1515
You can define the `Application` instance in several ways:
1616

17-
- Direct instantiation (which requires providing several dependencies).
18-
- The `AppFactory` (which will use sane defaults, but allows injecting alternate
17+
- Direct instantiation, which requires providing several dependencies.
18+
- The `AppFactory`, which will use sane defaults, but allows injecting alternate
1919
container and/or router implementations.
2020
- Via a dependency injection container; we provide a factory for setting up all
2121
aspects of the instance via configuration and other defined services.
@@ -50,6 +50,9 @@ public function __construct(
5050
);
5151
```
5252

53+
If no container is provided at instantiation, then all routed and piped
54+
middleware **must** be provided as callables.
55+
5356
### AppFactory
5457

5558
`Zend\Expressive\AppFactory` provides a convenience layer for creating an
@@ -64,6 +67,11 @@ AppFactory::create(
6467
);
6568
```
6669

70+
When no container or router are provided, it defaults to:
71+
72+
- zend-servicemanager for the container.
73+
- Aura.Router for the router.
74+
6775
### Container factory
6876

6977
We also provide a factory that can be consumed by a
@@ -114,7 +122,7 @@ Each of the methods `get()`, `post()`, `put()`, `patch()`, and `delete()`
114122
proxies to `route()` and has the signature:
115123

116124
```php
117-
public function route(
125+
function (
118126
$pathOrRoute,
119127
$middleware = null,
120128
$name = null
@@ -175,11 +183,14 @@ Routing is accomplished via dedicated a dedicated middleware method,
175183
`Application::routeMiddleware()`. It is an instance method, and can be
176184
piped/registered with other middleware platforms if desired.
177185

178-
Internally, any time `route()` is called (including via one of the proxy
179-
methods), or during `__invoke()` (the exposed application middleware), the
180-
instance will call `pipeRoutingMiddleware()`, which will pipe
181-
`Application::routeMiddleware` to the middleware pipeline. You can also pipe it
182-
manually if desired.
186+
Internally, the first time `route()` is called (including via one of the proxy
187+
methods), or, if never called, when `__invoke()` (the exposed application
188+
middleware) is called, the instance will pipe `Application::routeMiddleware` to
189+
the middleware pipeline. You can also pipe it manually if desired:
190+
191+
```php
192+
$app->pipeRoutingMiddleware();
193+
```
183194

184195
## Retrieving dependencies
185196

doc/book/container/factories.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Provided Factories
22

3-
zend-expressive provides several factories compatible with container-interop to
3+
Expressive provides several factories compatible with container-interop to
44
facilitate setting up common dependencies. The following is a list of provided
55
containers, what they will create, the suggested service name, and any
66
additional dependencies they may require.

doc/book/container/intro.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Containers
22

3-
zend-expressive promotes and advocates the usage of
3+
Expressive promotes and advocates the usage of
44
[Dependency Injection](http://www.martinfowler.com/articles/injection.html)/[Inversion of Control](https://en.wikipedia.org/wiki/Inversion_of_control)
5+
(also referred to as DI — or DIC — and IoC, respectively)
56
containers when writing your applications. These should be used for the
67
following:
78

@@ -21,10 +22,8 @@ examples.
2122

2223
At this time, we document support for the following specific containers:
2324

24-
- [zend-servicemanager](https://github.com/zendframework/zend-servicemanager):
25-
`composer require zendframework/zend-servicemanager`
26-
- [pimple-interop](https://github.com/moufmouf/pimple-interop):
27-
`composer require mouf/pimple-interop`
25+
- [zend-servicemanager](zend-servicemanager.md)
26+
- [pimple-interop](pimple.md)
2827

2928
> ## Service Names
3029
>

doc/book/cookbook.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ Let's assume the above represents an API.
2222
As your application progresses, you may have a mixture of different content, and now want to have
2323
the above segregated under the path `/api`.
2424

25-
To do that:
25+
This is essentially the same problem as addressed in the
26+
["Segregating your application to a subpath"](usage-examples.md#segregating-your-application-to-a-subpath] example.
27+
28+
To accomplish it:
2629

2730
- Create a new application.
2831
- Pipe the previous application to the new one, under the path `/api`.
@@ -41,6 +44,6 @@ $app->pipe('/api', $api);
4144
$app->run();
4245
```
4346

44-
The above works, because ever `Application` instance is itself middleware, and, more specifically,
47+
The above works, because every `Application` instance is itself middleware, and, more specifically,
4548
an instance of [Stratigility's `MiddlewarePipe`](https://github.com/zendframework/zend-stratigility/blob/master/doc/book/middleware.md),
4649
which provides the ability to compose middleware.

doc/book/emitters.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Emitters
2+
3+
To simplify the usage of Expressive, we added the `run()` method, which handles
4+
the incoming request, and emits a response.
5+
6+
The latter aspect, emitting the response, is the responsibility of an
7+
[emitter](https://github.com/zendframework/zend-diactoros/blob/master/doc/book/emitting-responses.md).
8+
An emitter accepts a response instance, and then does something with it, usually
9+
sending the response back to a browser.
10+
11+
Diactoros defines an `EmitterInterface`, and — as of the time we write this — a
12+
single emitter implementation, `Zend\Diactoros\Response\SapiEmitter`, which
13+
sends headers and output using PHP's standard SAPI mechanisms (the `header()`
14+
method and the output buffer).
15+
16+
We recognize that there are times when you may want to use alternate emitter
17+
implementations; for example, if you use [React](http://reactphp.org), the SAPI
18+
emitter will likely not work for you.
19+
20+
To facilitate alternate emitters, we offer two facilities:
21+
22+
- First, `Application` composes an emitter, and you can specify an alternate
23+
emitter during instantiation, or via the `Zend\Diactoros\Response\EmitterInterface`
24+
service when using the container factory.
25+
- Second, we provide `Zend\Expressive\Emitter\EmitterStack`, which allows you to
26+
compose multiple emitter strategies; the first to return a value other than
27+
boolean `false` will cause execution of the stack to short-circuit.
28+
`Application` composes an `EmitterStack` by default, with an `SapiEmitter`
29+
composed at the bottom of the stack.
30+
31+
## EmitterStack
32+
33+
The `EmitterStack` is an `SplStack` extension that implements
34+
`EmitterInterface`. You can add emitters to the stack by pushing them on:
35+
36+
```php
37+
$stack->push($emitterInstance);
38+
```
39+
40+
As a stack, execution is in LIFO (last in, first out) order; the first emitter
41+
on the stack will be evaluated last.

doc/book/error-handling.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Error Handling
22

3-
zend-expressive provides error handling out of the box, via zend-stratigility's [FinalHandler
3+
Expressive provides error handling out of the box, via zend-stratigility's [FinalHandler
44
implementation](https://github.com/zendframework/zend-stratigility/blob/master/doc/book/api.md#finalhandler).
55
This pseudo-middleware is executed in the following conditions:
66

@@ -38,7 +38,7 @@ optionally, a `Zend\Expressive\Template\TemplateInterface` instance, and templat
3838
404 and general error conditions. This makes it a good choice for use in production.
3939

4040
First, of course, you'll need to select a templating system and ensure you have
41-
the appropriate dependencies installed; see the [templating documentation](../template/intro.md)
41+
the appropriate dependencies installed; see the [templating documentation](template/intro.md)
4242
for information on what we support and how to install supported systems.
4343

4444
Once you have selected your templating system, you can setup the templated error
@@ -63,6 +63,9 @@ You can also use the `TemplatedErrorHandler` as a substitute for the `FinalHandl
6363
templated capabilities, by omitting the `TemplateInterface` instance when instantiating it. In this
6464
case, the response message bodies will be empty, though the response status will reflect the error.
6565

66+
See the section titled "Container Factories and Configuration", below, for techniques on configuring
67+
the `TemplatedErrorHandler` as your final handler within a container-based application.
68+
6669
## Whoops
6770

6871
[whoops](http://filp.github.io/whoops/) is a library for providing a more usable UI around
@@ -121,11 +124,17 @@ You can add more handlers if desired.
121124
Internally, when an exception is discovered, zend-expressive adds some data to the whoops output,
122125
primarily around the request information (URI, HTTP request method, route match attributes, etc.).
123126

127+
See the next section for techniques on configuring the `WhoopsErrorHandler` as your final handler
128+
within a container-based application.
129+
124130
## Container Factories and Configuration
125131

126132
The above may feel like a bit much when creating your application. As such, we provide several
127133
factories that work with [container-interop](https://github.com/container-interop/container-interop)-compatible
128134
container implementations to simplify setup.
129135

130-
See the [container factory documentation](../container/factories.md) for
131-
details.
136+
In each case, you should register the selected error handler's factory as the service
137+
`Zend\Expressive\FinalHandler`.
138+
139+
- For the `TemplatedErrorHandler`, use [`Zend\Expressive\Container\TemplatedErrorHandlerFactory`](container/factories.md#templatederrorhandlerfactory).
140+
- For the `WhoopsErrorHandler`, use [`Zend\Expressive\Container\WhoopsErrorHandlerFactory`](container/factories.md#whoopserrorhandlerfactory).

doc/book/features.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Overview
2+
3+
Expressive allows you to write [PSR-7](http://www.php-fig.org/psr/psr-7/)
4+
[middleware](https://github.com/zendframework/zend-stratigility/blob/master/doc/book/middleware.md)
5+
applications for the web.
6+
7+
PSR-7 is a standard defining HTTP message interfaces; these are the incoming
8+
request and outgoing response for your application. By using PSR-7, we ensure
9+
that your applications will work in other PSR-7 contexts.
10+
11+
Middleware is any code sitting between a request and a response; it typically
12+
analyzes the request to aggregate incoming data, delegates it to another layer
13+
to process, and then creates and returns a response. Middleware can and should
14+
be relegated only to those tasks, and should be relatively easy to write and
15+
maintain.
16+
17+
Middleware is also designed for composability; you should be able to nest
18+
middleware and re-use middleware.
19+
20+
With Expressive, you can build PSR-7-based middleware applications:
21+
22+
- APIs
23+
- Websites
24+
- Single Page Applications
25+
- and more.
26+
27+
## Features
28+
29+
Expressive builds on [zend-stratigility](https://github.com/zendframework/zend-stratigility)
30+
to provide a robust convenience layer on which to build applications. The
31+
features it provides include:
32+
33+
- **Routing**
34+
35+
Stratigility provides limited, literal matching only. Expressive allows you
36+
to utilize dynamic routing capabilities from a variety of routers, providing
37+
much more fine-grained matching capabilities. The routing layer also allows
38+
restricting matched routes to specific HTTP methods, and will return "405 Not
39+
Allowed" responses with an "Allow" HTTP header containing allowed HTTP
40+
methods for invalid requests.
41+
42+
Routing is abstracted in Expressive, allowing the developer to choose the
43+
routing library that best fits the project needs. By default, we provide
44+
wrappers for Aura.Router, FastRoute, and the zend-mvc router.
45+
46+
- **contaienr-interop**
47+
48+
Expressive encourages the use of Dependency Injection, and defines its
49+
`Application` class to compose a container-interop `ContainerInterface`
50+
instance. The container is used to lazy-load middleware, whether it is
51+
piped (Stratigility interface) or routed (Expressive).
52+
53+
- **Templating**
54+
55+
While Expressive does not assume templating is being used, it provides a
56+
templating abstraction. Developers can write middleware that typehints on
57+
this abstraction, and assume that the underlying adapter will provide
58+
layout support and namespaced template support.
59+
60+
- **Error Handling**
61+
62+
Applications should handle errors gracefully, but also handle them differently
63+
in development versus production. Expressive provides both basic error
64+
handling via Stratigility's own `FinalHandler` implementation, as well as
65+
more advanced error handling via two specialized error handlers: a templated
66+
error handler for production, and a Whoops-based error handler for development.

doc/book/quick-start.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Quick Start
22

3-
zend-expressive allows you to get started at your own pace. You can start with
3+
Expressive allows you to get started at your own pace. You can start with
44
the simplest example, detailed below, or move on to a more structured,
5-
configuration-driven approach as detailed in the [use case examples](examples.md).
5+
configuration-driven approach as detailed in the [use case examples](usage-examples.md).
66

77
## 1. Create a new project directory
88

doc/book/router/aura.md

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,23 @@ To use Aura.Router, you will first need to install it:
4444
$ composer require aura/router
4545
```
4646

47+
## Quick Start
48+
49+
At its simplest, you can instantiate a `Zend\Expressive\Router\Aura` instance
50+
with no arguments; it will create the underlying Aura.Router objects required
51+
and compose them for you:
52+
53+
```php
54+
use Zend\Expressive\Router\Aura;
55+
56+
$router = new Aura();
57+
```
58+
4759
## Programmatic Creation
4860

49-
To handle it programmatically, you will need to setup the Aura.Router instance
50-
manually, inject it into a `Zend\Expressive\Router\Aura` instance, and inject
51-
use that when creating your `Application` instance.
61+
If you need greater control over the Aura.Router setup and configuration, you
62+
can create the instances necessary and inject them into
63+
`Zend\Expressive\Router\Aura` during instantiation.
5264

5365
```php
5466
<?php
@@ -81,7 +93,65 @@ $app = AppFactory::create(null, $router);
8193

8294
[We recommend using an Inversion of Control container](../container/intro.md)
8395
for your applications; as such, in this section we will demonstrate
84-
defining two factories:
96+
two strategies for creating your Aura.Router implementation.
97+
98+
### Basic Router
99+
100+
If you don't need to provide any setup or configuration, you can simply
101+
instantiate and return an instance of `Zend\Expressive\Router\Aura` for the
102+
service name `Zend\Expressive\Router\RouterInterface`.
103+
104+
A factory would look like this:
105+
106+
```php
107+
// in src/Application/Container/RouterFactory.php
108+
namespace Application\Container;
109+
110+
use Interop\Container\ContainerInterface;
111+
use Zend\Expressive\Router\Aura;
112+
113+
class RouterFactory
114+
{
115+
/**
116+
* @param ContainerInterface $container
117+
* @return Aura
118+
*/
119+
public function __invoke(ContainerInterface $container)
120+
{
121+
return new Aura();
122+
}
123+
}
124+
```
125+
126+
You would register this with zend-servicemanager using:
127+
128+
```php
129+
$container->setFactory(
130+
'Zend\Expressive\Router\RouterInterface',
131+
'Application\Container\RouterFactory'
132+
);
133+
```
134+
135+
And in Pimple:
136+
137+
```php
138+
$pimple['Zend\Expressive\Router\RouterInterface'] = new Application\Container\RouterFactory();
139+
```
140+
141+
For zend-servicemanager, you can omit the factory entirely, and register the
142+
class as an invokable:
143+
144+
```php
145+
$container->setInvokableClass(
146+
'Zend\Expressive\Router\RouterInterface',
147+
'Zend\Expressive\Router\Aura'
148+
);
149+
```
150+
151+
### Advanced Configuration
152+
153+
If you want to provide custom setup or configuration, you can do so. In this
154+
example, we will be defining two factories:
85155

86156
- A factory to register as and generate an `Aura\Router\Router` instance.
87157
- A factory registered as `Zend\Expressive\Router\RouterInterface`, which

0 commit comments

Comments
 (0)