CakePHP4.0.4で標準追加されたBodyParserMiddlewareによってWebAPIアプリケーションが書きやすくなった
そういや表題の通りになったんだけど、Web上に情報がなかったから一筆したためてみたよ!
BodyParserMiddleware とは
CakePHP の Cookbook (リファレンス)には、以下のように書かれています。
cf. ボディパーサミドルウェア | ミドルウェア - CakePHP 4.x Strawberry Cookbook
アプリケーションが JSON、XML、またはその他のエンコードされたリクエストボディを受け入れる場合、
BodyParserMiddleware
を使用すると、それらのリクエストを配列にデコードして、$request->getParsedData()
および$request->getData()
で利用可能です。 デフォルトでは json ボディのみがパースされますが、オプションでXMLパースを有効にすることができます。 独自のパーサーを定義することもできます。
要は、 Content-Type: application/json
や Content-Type: application/xml
でリクエストされた際のリクエストボディをシュッとパースしてくれるミドルウェアです。
CakePHP 3.6.0 で class Cake\Http\Middleware\BodyParserMiddleware
が追加され、 CakePHPのアプリケーションテンプレートである cakephp/app には 4.0.4 で追加 されました。CakePHP4になってからデフォルトで使用される形になってます。
何が便利?
CakePHP3でWebAPIアプリケーションを書く場合、 Content-Type: application/json
でリクエストされた際のリクエストボディを Hash で受け取るには、以下のようにいちいち json_decode()
を噛ませる必要がありました。
リクエストボディの一部が欲しくても、一度リクエストボディの全体を受け止めてから部分にアクセスする、みたいなかんじで利便性に欠けていました。
<?php
namespace App\Controller;
// 中略
class ArticleController extends AppController
{
public function edit(string $id)
{
$postData = $this->getRequest()->input('json_decode', true);
$title = $postData['title'];
// 以下略
仮に Content-Type: application/x-www-form-urlencoded
や Content-Type: multipart/form-data
での POST リクエストだったら $_POST
に値が含まれるので、 $this->getRequest()->getData()
で取得することはできます。
でも、いまどき application/json
とか application/xml
でシュッとリクエストしたいじゃないですか〜〜🥺
(まあ、JavaScript / TypeScriptでHTTPクライアントとしてよく用いる axios なんかはデフォルトで Content-Type: application/x-www-form-urlencoded
だったりするんですけどね...うーん)
それを解決してくれるのが BodyParserMiddleware
です。 $type = 'application/json'
のような Content-Type 文字列が定義され、 Content-Type ごとに応じた $parser
クロージャを用いて処理してくれます。シュッとしてる!
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// 中略
$parser = $this->parsers[$type];
$result = $parser($request->getBody()->getContents());
if (!is_array($result)) {
throw new BadRequestException();
}
$request = $request->withParsedBody($result);
// 以下略
そして、 BodyParserMiddleware
で処理されたリクエストボディは、細かい意識をせずに $this->getRequest()->getData()
で取得できるようにリクエスト情報に格納してくれます。シュッとしてる!!
<?php
namespace App\Controller;
// 中略
class ArticleController extends AppController
{
public function edit(string $id)
{
$title = $this->getRequest()->getData('title');
// 以下略
おわりに
というわけで、WebAPIアプリケーションをCakePHP4で書く場合、よりシュッと書くために動いてくれている BodyParserMiddleware
について紹介してみました。
これでキミだけの最強のWebAPIアプリケーションを作ってみてな!!!
Discussion