公式サイト http://www.slimframework.com/ のサンプルだと、index.phpは
<?php use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; require 'vendor/autoload.php'; $app = new \Slim\App; $app->get('/hello/{name}', function (Request $request, Response $response, array $args) { $name = $args['name']; $response->getBody()->write("Hello, $name"); return $response; }); $app->run();
と書かれている一方で、「実際にプロジェクトを起こす時にベースに使うと便利」とされている、公式から出ているSlim-Skeletonのindex.php では、少しばかり、差異があります。
この辺を少し、読み解いていきましょう。
注意
一時期以降、結構ごっそりと書き方が変わっています。
一端 https://github.com/slimphp/Slim-Skeleton/tree/439b6ec6cb1189d0be7fe31f87af4cbeeb801e53 を前提に記述、後で最新用のフォローアップをします。
さて。
とりあえずまずはルーティングの設定です。
$app->get('/hello/{name}', function (Request $request, Response $response, array $args) { $name = $args['name']; $response->getBody()->write("Hello, $name"); return $response; });
このあたり、ですね。
これを、Pageが増える毎にindex.phpに重ねていくと、index.phpがえらいこと長くなってしまうので、ちょいと切り出してみましょう。
そうですねぇpublicにあるのも些か好ましさに欠けるかと思いますので。
publicディレクトリと同じレベルに、srcというディレクトリを切って、その中に routes.php とかいうファイルを作ってみましょう。
そうすると、まず切り出すので、index.phpが
<?php require 'vendor/autoload.php'; $app = new \Slim\App; // Register routes require __DIR__ . '/../src/routes.php'; $app->run();
こうなり、切り出したroutes.phpが
<?php use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; // Routes $app->get('/[{name}]', function (Request $request, Response $response, array $args) { // Sample log message $this->logger->info("Slim-Skeleton '/' route"); // Render index view return $this->renderer->render($response, 'index.phtml', $args); });
こうなります。
use句は、切り出したほうのコードで使ってるので、併せての移動ですね。
ついでに、 Psr\Http\Message\ServerRequestInterface はインタフェース宣言だけなので&Slimは実際にはちゃんとクラスまで切っているので。
implementsしたクラスに、use句を変更しておきましょう。
<?php use Slim\Http\Request; use Slim\Http\Response; // Routes $app->get('/[{name}]', function (Request $request, Response $response, array $args) { // Sample log message $this->logger->info("Slim-Skeleton '/' route"); // Render index view return $this->renderer->render($response, 'index.phtml', $args); });
さて。
index.phpですが。
このままでもよいのですが、実際にアプリケーションを組むのであれば「なにがしかの設定値」は、やはり欲しいところになります。
new \Slim\App でも、コンストラクタに色々と実際には設定を渡す事ができるので。
と言うわけで、設定値をやはり切り出して記載してみましょう。
ファイルは、src/settings.php にしてみます。
index.php
<?php require 'vendor/autoload.php'; // Instantiate the app $settings = require __DIR__ . '/../src/settings.php'; $app = new \Slim\App($settings); // Register routes require __DIR__ . '/../src/routes.php'; $app->run();
settings.php
<?php return [ 'settings' => [ 'displayErrorDetails' => true, // set to false in production 'addContentLengthHeader' => false, // Allow the web server to send the content-length header // Renderer settings 'renderer' => [ 'template_path' => __DIR__ . '/../templates/', ], // Monolog settings 'logger' => [ 'name' => 'slim-app', 'path' => isset($_ENV['docker']) ? 'php://stdout' : __DIR__ . '/../logs/app.log', 'level' => \Monolog\Logger::DEBUG, ], ], ];
これで「settings.phpに設定を書く」と「new \Slim\Appの引数として渡される」ので、色々な設定を入れ込む事ができるようになります。
次に。
diコンテナも少し設定をしておきましょう。
とりあえずざっくりと「view用のクラスとしてPhpRenderer」と、最低限の「logger(ログを出力するクラス)」くらいは追加しておきましょう。
追加用の設定は src/dependencies.php にでもいれておくことにします。
index.php
<?php require 'vendor/autoload.php'; // Instantiate the app $settings = require __DIR__ . '/../src/settings.php'; $app = new \Slim\App($settings); // Set up dependencies require __DIR__ . '/../src/dependencies.php'; // Register routes require __DIR__ . '/../src/routes.php'; $app->run();
dependencies.php
<?php // DIC configuration $container = $app->getContainer(); // view renderer $container['renderer'] = function ($c) { $settings = $c->get('settings')['renderer']; return new Slim\Views\PhpRenderer($settings['template_path']); }; // monolog $container['logger'] = function ($c) { $settings = $c->get('settings')['logger']; $logger = new Monolog\Logger($settings['name']); $logger->pushProcessor(new Monolog\Processor\UidProcessor()); $logger->pushHandler(new Monolog\Handler\StreamHandler($settings['path'], $settings['level'])); return $logger; };
これで一段落……したいところなのですが。
ついでに、middleware用の設定をいれる場所を作っておきましょう。
一端「場所だけ」を作る感じで、 src/middleware.php に用意をしておきます。
index.php
<?php require 'vendor/autoload.php'; // Instantiate the app $settings = require __DIR__ . '/../src/settings.php'; $app = new \Slim\App($settings); // Set up dependencies require __DIR__ . '/../src/dependencies.php'; // Register middleware require __DIR__ . '/../src/middleware.php'; // Register routes require __DIR__ . '/../src/routes.php'; $app->run();
middleware.php
<?php // Application middleware // e.g: $app->add(new \Slim\Csrf\Guard);
こんなところでしょうか。
ちなみに、サンプルで書かれている「\Slim\Csrf\Guard」は、これそのものではなくてもよいので、なにがしかCSRF対策用のものをいれておくのは、大変に好ましいと思われます。
これで、おおよそ「Slim-Skeletonのindex.php」と同じもの、になります。
実際のSlim-Skeletonのindex.phpは
<?php if (PHP_SAPI == 'cli-server') { // To help the built-in PHP dev server, check if the request was actually for // something which should probably be served as a static file $url = parse_url($_SERVER['REQUEST_URI']); $file = __DIR__ . $url['path']; if (is_file($file)) { return false; } } require __DIR__ . '/../vendor/autoload.php'; session_start(); // Instantiate the app $settings = require __DIR__ . '/../src/settings.php'; $app = new \Slim\App($settings); // Set up dependencies require __DIR__ . '/../src/dependencies.php'; // Register middleware require __DIR__ . '/../src/middleware.php'; // Register routes require __DIR__ . '/../src/routes.php'; // Run app $app->run();
となっていて。
空改行の箇所をのぞくと
・先頭の9行
・session_start();
くらいの差異、ですね。
先頭の9行は大雑把に
・ビルトインウェブサーバーを使っている時に「staticなURI(実在するファイルのURI)がcallされたら、プログラム的な処理をしない」ためのロジック
になります。
session_start()は、そのまま。
まぁセッションを使うことは「極めて多い」ですからねぇ。
と、このような感じで。plainのSlimのindex.phpから、Slim-Skeletonのindex.phpに移り変わりが行われています。
……という感じだったのですが。6 Nov 2018の
https://github.com/slimphp/Slim-Skeleton/tree/8dd2f8469514a43d4180148466a832f8d1683fe4
のタイミングで、ちょいと諸々、がらっと様変わりをしたようなので、少し覗き直してみましょう。
index.phpですが、こんな風になっています。
<?php if (PHP_SAPI == 'cli-server') { // To help the built-in PHP dev server, check if the request was actually for // something which should probably be served as a static file $url = parse_url($_SERVER['REQUEST_URI']); $file = __DIR__ . $url['path']; if (is_file($file)) { return false; } } require __DIR__ . '/../vendor/autoload.php'; session_start(); // Instantiate the app $settings = require __DIR__ . '/../src/settings.php'; $app = new \Slim\App($settings); // Set up dependencies App\Dependencies::init($app); // Register middleware App\Middleware::init($app); // Register routes App\Routes::init($app); // Run app $app->run();
全体的に「クラス名::init($app)」の方法でのcallに変わっている感じですね。
例えばRoutesを見ると
<?php namespace App; use Slim\App; use Slim\Http\Request; use Slim\Http\Response; /** * Configures the routes * @param App $app */ class Routes { /** * Configures the routes * @param App $app */ public static function init(App $app) { $container = $app->getContainer(); $app->get('/[{name}]', function (Request $request, Response $response, array $args) use ($container) { // Sample log message $container->get('logger')->info("Slim-Skeleton '/' route"); // Render index view return $container->get('renderer')->render($response, 'index.phtml', $args); }); } }
という感じで、全体的に「クラスの中のstaticなメソッドでの定義」に変わっているようです。
で、その状況が、わずか二週間弱、19 Nov 2018 に
https://github.com/slimphp/Slim-Skeleton/tree/15fc5968d9430e67110d82dff3b1b3a2349c9cf6
で、もう一度変わっています。
<?php if (PHP_SAPI == 'cli-server') { // To help the built-in PHP dev server, check if the request was actually for // something which should probably be served as a static file $url = parse_url($_SERVER['REQUEST_URI']); $file = __DIR__ . $url['path']; if (is_file($file)) { return false; } } require __DIR__ . '/../vendor/autoload.php'; session_start(); // Instantiate the app $settings = require __DIR__ . '/../src/settings.php'; $app = new \Slim\App($settings); // Set up dependencies $dependencies = require __DIR__ . '/../src/dependencies.php'; $dependencies($app); // Register middleware $middleware = require __DIR__ . '/../src/middleware.php'; $middleware($app); // Register routes $routes = require __DIR__ . '/../src/routes.php'; $routes($app); // Run app $app->run();
で、routesが
<?php use Slim\App; use Slim\Http\Request; use Slim\Http\Response; return function (App $app) { $container = $app->getContainer(); $app->get('/[{name}]', function (Request $request, Response $response, array $args) use ($container) { // Sample log message $container->get('logger')->info("Slim-Skeleton '/' route"); // Render index view return $container->get('renderer')->render($response, 'index.phtml', $args); }); };
前回「staticなクラスメソッド」だったのが、今回は「無名関数」に置き換わっている感じですね。
なんか色々と動きがありそうな感じなので、ちょっと興味深く思いました。