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

Commit eae0bd6

Browse files
committed
Merge branch 'hotfix/helper-body-params-docs'
Close #243
2 parents 37a3618 + e246277 commit eae0bd6

File tree

4 files changed

+192
-2
lines changed

4 files changed

+192
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Fifth release candidate.
1616
a subdirectory of your web root.
1717
- [#239](https://github.com/zendframework/zend-expressive/pull/239) adds a
1818
cookbook recipe detailing how to create modular Expressive applications.
19+
- [#243](https://github.com/zendframework/zend-expressive/pull/243) adds a
20+
chapter to the helpers section detailing the new `BodyParseMiddleware`.
1921

2022
### Deprecated
2123

doc/book/helpers/body-parse.md

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
# BodyParse Middleware
2+
3+
`Zend\Expressive\Helper\BodyParse\BodyParseMiddleware` provides generic PSR-7
4+
middleware for parsing the request body into parameters, and returning a new
5+
request instance that composes them. The subcomponent provides a strategy
6+
pattern around matching the request `Content-Type`, and then parsing it, giving
7+
you a flexibile approach that can grow with your accepted content types.
8+
9+
By default, this middleware will detect the following content types:
10+
11+
- `application/x-www-form-urlencoded` (standard web-based forms, without file
12+
uploads)
13+
- `application/json`, `application/*+json` (JSON payloads)
14+
15+
## Registering the middleware
16+
17+
You can register it manually:
18+
19+
```php
20+
use Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware;
21+
22+
$app->pipe(BodyParamsMiddleware::class);
23+
24+
// register other middleware
25+
// register routing middleware
26+
$app->run();
27+
```
28+
29+
or as `pre_routing` pipeline middleware:
30+
31+
```php
32+
// config/autoload/middleware-pipeline.global.php
33+
use Zend\Expressive\Helper;
34+
35+
return [
36+
'dependencies' => [
37+
'invokables' => [
38+
Helper\BodyParams\BodyParamsMiddleware::class => Helper\BodyParams\BodyParamsMiddleware::class,
39+
/* ... */
40+
],
41+
'factories' => [
42+
/* ... */
43+
],
44+
],
45+
'middleware_pipeline' => [
46+
'pre_routing' => [
47+
[ 'middleware' => Helper\BodyParams\BodyParamsMiddleware::class ],
48+
/* ... */
49+
],
50+
'post_routing' => [
51+
/* ... */
52+
],
53+
],
54+
];
55+
```
56+
57+
Another option is to incorporate it in route-specific middleware queues:
58+
59+
```php
60+
// config/autoload/routes.global.php
61+
use Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware;
62+
63+
return [
64+
'dependencies' => [
65+
'invokables' => [
66+
Helper\BodyParams\BodyParamsMiddleware::class => Helper\BodyParams\BodyParamsMiddleware::class,
67+
/* ... */
68+
],
69+
'factories' => [
70+
/* ... */
71+
],
72+
],
73+
'routes' => [
74+
[
75+
'name' => 'contact:process',
76+
'path' => '/contact/process',
77+
'middleware' => [
78+
BodyParamsMiddleware::class,
79+
Contact\Process::class,
80+
],
81+
'allowed_methods' => ['POST'],
82+
]
83+
],
84+
];
85+
```
86+
87+
This latter approach has a slight advantage: the middleware will only execute
88+
for routes that require the processing. While the middleware has some checks to
89+
ensure it only triggers for HTTP methods that accept bodies, those checks are
90+
still overhead that you might want to avoid; the above strategy of using the
91+
middleware only with specific routes can accomplish that.
92+
93+
## Strategies
94+
95+
If you want to intercept and parse other payload types, you can add *strategies*
96+
to the middleware. Strategies implement `Zend\Expressive\Helper\BodyParams\StrategyInterface`:
97+
98+
```php
99+
namespace Zend\Expressive\Helper\BodyParams;
100+
101+
use Psr\Http\Message\ServerRequestInterface;
102+
103+
interface StrategyInterface
104+
{
105+
/**
106+
* Match the content type to the strategy criteria.
107+
*
108+
* @param string $contentType
109+
* @return bool Whether or not the strategy matches.
110+
*/
111+
public function match($contentType);
112+
113+
/**
114+
* Parse the body content and return a new response.
115+
*
116+
* @param ServerRequestInterface $request
117+
* @return ServerRequestInterface
118+
*/
119+
public function parse(ServerRequestInterface $request);
120+
}
121+
```
122+
123+
You then register them with the middleware using the `addStrategy()` method:
124+
125+
```php
126+
$bodyParams->addStrategy(new MyCustomBodyParamsStrategy());
127+
```
128+
129+
To automate the registration, we recommend writing a factory for the
130+
`BodyParamsMiddleware`, and replacing the `invokables` registration with a
131+
registration in the `factories` section of the `middleware-pipeline.config.php`
132+
file:
133+
134+
```php
135+
use Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware;
136+
137+
class MyCustomBodyParamsStrategyFactory
138+
{
139+
public function __invoke($container)
140+
{
141+
$bodyParams = new BodyParamsMiddleware();
142+
$bodyParams->addStrategy(new MyCustomBodyParamsStrategy());
143+
return $bodyParams;
144+
}
145+
}
146+
147+
// In config/autoload/middleware-pipeline.config.php:
148+
use Zend\Expressive\Helper;
149+
150+
return [
151+
'dependencies' => [
152+
'invokables' => [
153+
// Remove this line:
154+
Helper\BodyParams\BodyParamsMiddleware::class => Helper\BodyParams\BodyParamsMiddleware::class,
155+
/* ... */
156+
],
157+
'factories' => [
158+
// Add this line:
159+
Helper\BodyParams\BodyParamsMiddleware::class => MyCustomBodyParamsStrategy::class,
160+
/* ... */
161+
],
162+
],
163+
];
164+
```
165+
166+
## Removing the default strategies
167+
168+
By default, `BodyParamsMiddleware` composes the following strategies:
169+
170+
- `Zend\Expressive\Helper\BodyParams\FormUrlEncodedStrategy`
171+
- `Zend\Expressive\Helper\BodyParams\JsonStrategy`
172+
173+
These provide the most basic approaches to parsing the request body. They
174+
operate in the order they do to ensure the most common content type —
175+
`application/x-www-form-urlencoded` — matches first, as the middleware
176+
delegates parsing to the first match.
177+
178+
If you do not want to use these default strategies, you can clear them from the
179+
middleware using `clearStrategies()`:
180+
181+
```php
182+
$bodyParamsMiddleware->clearStrategies();
183+
```
184+
185+
Note: if you do this, **all** strategies will be removed! As such, we recommend
186+
doing this only immediately before registering any custom strategies you might
187+
be using.

doc/book/helpers/bookdown.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"content": [
44
{"Introduction": "intro.md"},
55
{"UrlHelper": "url-helper.md"},
6-
{"ServerUrlHelper": "server-url-helper.md"}
6+
{"ServerUrlHelper": "server-url-helper.md"},
7+
{"Body Parsing Middleware": "body-parse.md"}
78
]
89
}

mkdocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pages:
1010
- { 'Routing Adapters': [{ Introduction: router/intro.md }, { 'Routing Interface': router/interface.md }, { 'URI Generation': router/uri-generation.md }, { 'Route Result Observers': router/result-observers.md }, { 'Routing vs Piping': router/piping.md }, { 'Using Aura': router/aura.md }, { 'Using FastRoute': router/fast-route.md }, { 'Using the ZF2 Router': router/zf2.md }] }
1111
- { Templating: [{ Introduction: template/intro.md }, { 'Template Renderer Interface': template/interface.md }, { 'Templated Middleware': template/middleware.md }, { 'Using Plates': template/plates.md }, { 'Using Twig': template/twig.md }, { 'Using zend-view': template/zend-view.md }] }
1212
- { 'Error Handling': error-handling.md }
13-
- { Helpers: [{ Introduction: helpers/intro.md }, { UrlHelper: helpers/url-helper.md }, { ServerUrlHelper: helpers/server-url-helper.md }] }
13+
- { Helpers: [{ Introduction: helpers/intro.md }, { UrlHelper: helpers/url-helper.md }, { ServerUrlHelper: helpers/server-url-helper.md }, { 'Body Parsing Middleware': helpers/body-parse.md }] }
1414
- { Emitters: emitters.md }
1515
- { Examples: usage-examples.md }
1616
- { Cookbook: [{ 'Prepending a common path to all routes': cookbook/common-prefix-for-routes.md }, { 'Route-specific middleware pipelines': cookbook/route-specific-pipeline.md }, { 'Setting custom 404 page handling': cookbook/custom-404-page-handling.md }, { 'Registering custom view helpers when using zend-view': cookbook/using-custom-view-helpers.md }, { 'Using zend-form view helpers': cookbook/using-zend-form-view-helpers.md }, { 'Using Expressive from a subdirectory': cookbook/using-a-base-path.md }, { 'Building modular applications': cookbook/modular-layout.md }] }

0 commit comments

Comments
 (0)