公式サイト 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なクラスメソッド」だったのが、今回は「無名関数」に置き換わっている感じですね。
なんか色々と動きがありそうな感じなので、ちょっと興味深く思いました。