概要
LaravelでAPIを作っていて共通レスポンスをAPI毎に入れ込むのではなくどこかで自動的に付与させたかった。
ぐぐったらmiddlewareを作ってhookさせるようなやり方が出てきたが一度作成されたデータをパースして作り直すのがなんか嫌だったのでもう少し調査し、このやり方にたどり着いた。
登場するコードは結構実際に利用した所からqiita用に起こしてるのでちょっと変な箇所があるかも。
筆者はLaravel初学者です。
環境
PHP
PHP 7.4.3 (cli) (built: Feb 20 2020 21:53:46) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.3, Copyright (c), by Zend Technologies
with Xdebug v2.9.5, Copyright (c) 2002-2020, by Derick Rethans
Laravel
Laravel Framework 6.18.15
そもそもレスポンスってどこで作られてんだろう?
レスポンス作ってるところが判ればカスタマイズの方法がわかるじゃろうと思い追っていったところ
src/Illuminate/Routing/Router.php#L719にprepareResponse
を発見。
名前的にここだろうと的を絞る。
実際にRouterを拡張していく
app/Routing
ディレクトリを作成しRouterクラスを作成
app/Routing/Router.php
<?php
namespace App\Routing;
use Illuminate\Routing\Router as BaseRouter;
class Router extends BaseRouter
{
public function prepareResponse($request, $response)
{
// ここに独自の処理を追加する
// toResponseの中で色々判断してるのでここで受けるresponseは配列、Arrayable、ArrayObjectの方が取り扱いやすい
return static::toResponse($request, $response);
}
}
拡張したRouterを利用できるようにする
src/bootstrap/app.php
に定義を追加する
src/bootstrap/app.php
$app->singleton('router', function ($app) {
return new App\Routing\Router($app['events'], $app);
});
コントローラーのレスポンスを変更
response()->json
で共通パラメーターを含め返却していた部分をAPIの責任のあるパラメーターだけを配列で返却するだけにした。
public function api()
{
- return response()->json([
- 'state' => 1, // 共通レスポンス
- 'timestamp' => time(), // 共通レスポンス
- 'result' => "API独自の結果"
- ]);
+ return [
+ 'result' => "API独自の結果"
+ ];
}
まとめ
このやり方なら一度JsonResponseに変換されたレスポンスを再度配列に変換し、データを結合してから再度JsonResponseに変換する必要がなくて良いのかなと。