Slim4 の Slim-Skelton をカスタマイズして dotenv, Whoops, debugbar を入れる

Slim4 を触ってみようと思い立ったのでメモ。 Slim3 のときは上述参考記事の通りに Slim-Skelton に dotenv(vlucas/phpdotenv) や whoops(dopesong/Slim-Whoops) 等を導入したのですが、 Slim のバージョンが4に上がって同じやり方ができなくなってしまいました。 そこで、同じようなことができないかと試した方法を以下に記します。

ベース

ベースとして使用するのはslimphp/Slim-Skeleton: Slim Framework 4 Skeleton Application。公式なので Slim4 版ですね。
public/vendor
.env
composer.lock
.gitignoreに上述3行を追加。
{
    "name": "slim/slim-skeleton",
    "description": "A Slim Framework skeleton application for rapid development",
    "keywords": [
        "microframework",
        "rest",
        "router",
        "psr7"
    ],
    "homepage": "http://github.com/slimphp/Slim-Skeleton",
    "license": "MIT",
    "authors": [
        {
            "name": "Josh Lockhart",
            "email": "info@joshlockhart.com",
            "homepage": "http://www.joshlockhart.com/"
        },
        {
            "name": "Pierre Berube",
            "email": "pierre@lgse.com",
            "homepage": "http://www.lgse.com/"
        }
    ],
    "require": {
        "ext-json": "*",
        "monolog/monolog": "^1.24",
        "php": ">=7.1",
        "php-di/php-di": "^6.0",
        "slim/psr7": "^0.5",
        "slim/slim": "^4.1",
        "vlucas/phpdotenv": "v4.1.0"
    },
    "require-dev": {
        "phpunit/phpunit": "^7.5",
        "squizlabs/php_codesniffer": "^3.5.3",
        "phpmd/phpmd": "^2.8.1",
        "zeuxisoo/slim-whoops": "^0.7.2"
    },
    "config": {
        "process-timeout": 0,
        "sort-packages": true,
        "vendor-dir": "public/vendor"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },
    "scripts": {
        "start": "php -S localhost:8080 -t public",
        "test": "phpunit",
        "phpcs": "phpcs --standard=PSR2 src/",
        "phpmd": "phpmd src/ text cleancode,codesize,design,unusedcode"
    }
}
composer.jsonに各種追加。
require __DIR__ . '/vendor/autoload.php'; // modified
public/index.phpのautoloadのディレクトリを書き換えます。これはcomposer.jsonconfig"vendor-dir": "public/vendor"と、vendorの位置を変える記述をしたため。 この変更を行った理由については最後のdebugbarの追加の部分で。

phpdotenv

これについては Slim3 とほぼ同様。
require __DIR__ . '/../vendor/autoload.php';

// added
$dot_env = __DIR__. '/../.env';
if (is_readable($dot_env)) {
    $dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/../');
    $dotenv->load();
}

// Instantiate PHP-DI ContainerBuilder
$containerBuilder = new ContainerBuilder();
ただしphpdotenv自体が新しくなっているのでpublic/index.phpの微妙に書き方を変えました。
    // Global Settings Object
    $containerBuilder->addDefinitions([
        'settings' => [
            'debug' => getenv('DEBUG'),    // added
            'displayErrorDetails' => true, // Should be set to false in production
            'logger' => [
                'name' => 'slim-app',
app/settings.phpに1行追加。

whoops

Slim3 で使用していたdopesong/Slim-Whoopsが更新されていないので、 Slim4 対応している別のwhoops(zeuxisoo/php-slim-whoops)を使用することにします。
<?php
declare(strict_types=1);
use App\Application\Middleware\SessionMiddleware;
use Slim\App;
return function (App $app) {
    $app->add(SessionMiddleware::class);

    // added
    $c = $app->getContainer();
    if ((bool)($c->get('settings')['debug'] ?? false)) {
        $app->add(new Zeuxisoo\Whoops\Slim\WhoopsMiddleware(['enable' => true]));
    } else {
        $errorMiddleware = $app->addErrorMiddleware(false, true, true);
        $errorHandler    = $errorMiddleware->getDefaultErrorHandler();
        $errorHandler->registerErrorRenderer('text/html', HtmlErrorRenderer::class);
    }
};
app/middleware.phpに上述コードを追加。コードはCustom error rendering in Slim 4 – Rob Allen’s DevNotesより。 ちなみにRob Allen(akrabat)さんはSlimのメンテナーの一人。……道理でSlim関係を検索するとよくヒットすると思った。

debugbar

debugbarもkitchenu/Slim-DebugBarが Slim3 で止まっているので、maximebf/php-debugbarを使用。
// 略
use Psr\Log\LoggerInterface;
use DebugBar\StandardDebugBar; // added

return function (ContainerBuilder $containerBuilder) {
    $containerBuilder->addDefinitions([
// 略
        DebugBar::class => function (ContainerInterface $c) { // added
            $debugbar = new StandardDebugBar();
            $debugbar->addCollector(new DebugBar\Bridge\MonologCollector($c->get(LoggerInterface::class)));
            $renderer = $debugbar->getJavascriptRenderer();
            $renderer->setIncludeVendors(false);
            return $debugbar;
        },
    ]);
};
app/dependencies.phpに以上を追加。
return function (App $app) {
    $c = $app->getContainer();
    $app->get('/', function (Request $request, Response $response) use ($c) {
        $renderHead = '';
        $renderBottomBody = '';
        if ((bool)($c->get('settings')['debug'] ?? false)) {
            $debugbar = $c->get(DebugBar::class);
            $debugbarRenderer = $debugbar->getJavascriptRenderer();
            $renderHead = <<<eof
        <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
        {$debugbarRenderer->renderHead()}
eof;
        $renderBottomBody = $debugbarRenderer->render();
        }
        $bodyText = 'Hello world!';
        $body = <<<eof
<html>
    <head>
{$renderHead}
    </head>
    <body>
        <h1>{$bodyText}</h1>

{$renderBottomBody}
    </body>
</html>
eof;
        $response->getBody()->write($body);
        return $response;
    });
app/routes.phpのルートのルーティングを書き換え。コードについてはやはりDependency Injection in Slim 4 – Rob Allen’s DevNotesより。 ここまででPHP的には動作をするのですが、debugbarがvendorディレクトリ内のcssやらJSやらを読み込もうとします。 そのため、composer startことphp -S localhost:8080 -t publicでPHPのビルドインWebサーバを起動した場合はリソースが読み込めずにコンソールに404エラーを吐きます。 そこで冒頭のようにvendorディレクトリをpublic内に持ってきました。 この変更により、debugbarが表示されるようになりました。 ついでに.envDEBUG=1と記述した場合はdebugbar表示、そうれなければ非表示、というように条件分岐を追記しておきました。

動作確認

カスタマイズしたSlim4-Skeletonの動作確認
カスタマイズしたSlim4-Skeletonの動作確認
DebugBarも出ていますね。

成果物

カスタマイズしたものをGithubのリポジトリに置いておきました。

参考

この記事を書いた人

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。