【PHP/Slim4】１．軽量フレームワーク(Slim4-skeleton) 環境構築

軽量な機能のWeb APIを作成したい
Laravelのようなフルスタックではなく、軽量なフレームワークで簡単に構築したい
ということで、Slim4を使ってみたときのメモ書き

## Step1．Slim4-skeleton環境の構築
git bashなどcomposeが使える環境を用意し、以下のコマンドを実行
Slim4-skeletonプロジェクト一式がダウンロードされる
~~~js
composer create-project slim/slim-skeleton [任意のプロジェクト名]
~~~

#### 補足．フォルダ構成について
最上位の親ディレクトリは、上記のコマンドで入力した「プロジェクト名」でフォルダが生成される
|階層１|階層２|階層３|編集|概要|
|---|---|---|---|---|
|app|dependencies.php||〇|ライブラリのコンテナ生成<br>Twingなどのライブラリをcomposeで追加後、依存関係の解決|
||settings.php||〇|環境変数設定やライブラリの設定
||middleware.php||〇|ライブラリを追加時、middlewareに依存関係を注入（Twingなどは必要）
||repositories.php||〇|自分が作成したApplicationの依存関係の解決
||routes.php||〇|URL振り分け、public/index.phpから遷移してくる|
|logs|||×|Slimログの出力先|
|public|||〇|Slim4の公開ディレクトリ<br>index.phpやcss/JavaScriptを格納|
|src|Application|Actions|〇|MVCの"VC"相当<br>・routes.phpから受け取ったデータの振り分け<br>・後述Domainとのやり取り<br>・Responseのレンダリング|
|||Handlers|×|基本編集は不要|
|||Middleware|×|同上|
|||ResponseEmitter|×|同上|
|||Settings|×|同上|
||Domain|DomainException|〇|MVCの"M"相当<br>・データ構造クラスの定義、I/Fの定義<br>・ビジネスロジックも表現|
||Infrastructure||〇|MVCの"M"相当<br>・Model のデータ永続化を抽象化したオブジェクト<br>・データ取得(外部API,DB接続)として利用するなどでもよい|
|var|||×|Slim4のキャッシュファイルフォルダ<br>コード反映が表示が更新されない場合、このフォルダ配下のキャッシュファイルを削除すると解決|
|vendor|||×|Slim4本体ソースや追加したライブラリのソース格納先|

## Step2．ログ出力設定
Monologの設定を行いログ出力を設定/カスタマイズする
#### public/index.php
~~~php
use DI\ContainerBuilder;
use Psr\Log\LoggerInterface; // ★追加
use Slim\Factory\AppFactory;
use Slim\Factory\ServerRequestCreatorFactory;

：(中略)

// Create Error Handler
$responseFactory = $app->getResponseFactory();
//$errorHandler = new HttpErrorHandler($callableResolver, $responseFactory); // ★コメントアウト
$logger = $container->get(LoggerInterface::class); // ★追加
$errorHandler = new HttpErrorHandler($callableResolver, $responseFactory, $logger); // ★追加
~~~

#### app/settings.php
~~~php
    // Global Settings Object
    $containerBuilder->addDefinitions([
        SettingsInterface::class => function () {
            return new Settings([
                'displayErrorDetails' => true,//★本番運用時falseにする。エラー詳細が画面に表示される
                'logError'            => true,//★変更
                'logErrorDetails'     => true,//★変更
                'logger' => [
                    'name' => 'slim-app',
                    'path' => isset($_ENV['docker']) ? 'php://stdout' : __DIR__ . '/../logs/app.log',
                    'level' => Logger::DEBUG,
                ],
~~~

プロジェクト内で存在しないURLなどアクセスを行い、HTTP404などのエラーを起こすと、logs/app.logが生成される

ログのフォーマットを変更したい場合は、以下のような編集を行う
#### app/dependencies.php
~~~php
use Monolog\Processor\UidProcessor;
use Monolog\Formatter\LineFormatter; // ★追加 ログフォーマット変更
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;

：（中略）

return function (ContainerBuilder $containerBuilder) {
	$containerBuilder->addDefinitions([
		LoggerInterface::class => function (ContainerInterface $c) {
			$settings = $c->get(SettingsInterface::class);

			$loggerSettings = $settings->get('logger');
			$logger = new Logger($loggerSettings['name']);

			$processor = new UidProcessor();
			$logger->pushProcessor($processor);

			$handler = new StreamHandler($loggerSettings['path'], $loggerSettings['level']);

			// ★フォーマット変更 
   			// 形式例）日時、アクセス元IP、ログレベル、ログメッセージ
			$date_format = 'Y-n-d H:i:s.u';
			$userId = $_SERVER['REMOTE_ADDR'];
			$format = "%datetime%,{$userId},%level_name%,%message%" . PHP_EOL;
			$formatter = new LineFormatter($format, $date_format, true);
			$handler->setFormatter($formatter);


			$logger->pushHandler($handler);
			return $logger;
		},
~~~



## Step3．WebサーバのDocumentRootにアップロードする
PHPが動作するWebサーバのDocumentRootにアップロードを行う
XAMPPなどのローカル環境で確認する場合、index.phpに以下の編集を行いパスを通す

#### public/index.php
~~~php
// プロジェクト ベースURL  ★追加
$app->setBasePath(getBasePath());

// Run App & Emit Response
$response = $app->handle($request);
$responseEmitter = new ResponseEmitter();
$responseEmitter->emit($response);

// Get Base Path  ★追加
function getBasePath() {
	$basePath = str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME']));
	if ($basePath == '/') return '';
	return $basePath;
}
~~~

## Step4．サンプルコードの動作確認を行う
上記のサンプルコードにアクセスを行い、それぞれ結果が表示されれば基本環境が構築できている
例１）http://localhost/[プロジェクト名]/public
例２）http://localhost/[プロジェクト名]/public/users
例３）http://localhost/[プロジェクト名]/public/users/1