時にデモなどで想定していないバージョンの PHP 環境でプログラムを動かす必要に駆られます。そういった時、プログラムを動かすのを諦めてデモとして成り立つ動作ができるように API をモックを作ることがあります。この記事ではそういう時のためのコードを紹介します。
まずは次のミドルウェアコードです。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Storage;
class ResponseToJson
{
public function handle(Request $request, Closure $next)
{
$response = $next($request);
// 無暗にロギングしないための設定
if ($response instanceof JsonResponse && config('app.logging_api_json')) {
// あるストレージにレスポンスの中身をアクセスされた URL で書き込み
// GET のパラメータを表す ? マークはディレクトリパスとして使えないので ### に置き換え
Storage::disk('api_response_mock')->put(
str_replace('?', '###', $_SERVER['REQUEST_URI']).'.json',
$response->content()
);
}
return $response;
}
}
このコードをミドルウェアに設置して config を追加して \App\Http\Kernel::$middlewareGroups に登録すれば、次の様に API レスポンスが JSON ファイルになって保存されます。
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
ResponseToJson::class, // ここ
],
'api' => [
'throttle:60,1',
'bindings',
ResponseToJson::class, // ここ
],
];

こんな感じで json ファイルをデモに必要なだけ準自動生成します(別途 API を叩く必要あり)。次に用意した json を返す PHP コードです。これを様々なリクエストを吸う PHP ファイルとして置けばほとんどの PHP のバージョンでモックを返すスクリプトが動くようになります。
<?php
// アクセスされた URL を置き換えて json ファイルのパスに変換
// '/public' を '' に、 '?' を '###' に置換
$contentPath = __DIR__.'/../storage/api_response_mock'.str_replace(['/public', '?'], ['', '###'], $_SERVER['REQUEST_URI']).'.json';
// json ファイルが存在するならばその中身を echo
if (file_exists($contentPath)) {
echo file_get_contents($contentPath);
} else {
// 存在しなければ、適当にハンドリング
// 例では React 想定で API 以外は React を呼ぶ根元になる view.html を echo します
echo file_get_contents(__DIR__.'/view.html');
}
# nginx 設定ファイルがこんな感じだったら /work/backend/public/index.php として↑スクリプトを設置
root /work/backend/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
この様にすると、環境をそれ程問わずデモ用のプログラムを動かせます。ミドルウェアに関しては保存された json ファイルを元に TypeScript の型ファイルを作ること(置換でちょちょいと)もできて便利です。