軽量PHPフレームワークSlimを使ってサクッとWebアプリひな形を作ってみる
PHPには数多くのフレームワークがあります。
LaravelやCakePHPのようなWebアプリ開発に必要な機能が一通りそろったフレームワークをフルスタックフレームワークと呼ぶのに対し、Slimは軽量フレームワーク(マイクロフレームワーク)と呼ばれます。
フルスタックフレームワークとの違いは、必要最小限の機能だけを有していることによる、学習コストの低さと、軽量さ(ファイルサイズ、実行速度)です。
Slimを使って必要最小限の機能を備えたWebアプリのひな形を作ってみます。
公式サイト
GitHub
バージョン4が出てますが3系の方が分かりやすかったのでこちらを使います。
まっさらな状態で始めることもできますが、スケルトンと呼ばれる、初期構成のフォルダ・ファイルが用意されたものでプロジェクトを作成します。
このページの処理を追いかけてフレームワークの詳細をつかみます。
エラー表示の有無や、テンプレートやログの配置をここで設定しています。
任意のキーでユーザー独自の設定も作れます。
設定は次のようにフレームワーク内で取得できます。
デフォルトではテンプレートエンジンとログの依存関係が設定してあります。
例えばロガーのコンポーネントを変えてもフレームワーク上は
例えばデバッグツールバーの設定をここで行ったりします。
上に書いたものから順にURLのパターンとhttpsメソッドに一致するか見ていき、一致した場合割り当てられた関数の処理が実行されます。
サンプルページは、URLの文字列を$name変数に入れ、
以上がSlim3フレームワークの処理の大まかな流れです。
フルスタックフレームワークに比べシンプルでわかりやすいですね。
コントローラーをクラスとして独立させて、ルーティングではメソッドを呼び出すだけにしてみます。
先にdotenvを使えるようにして、そこにDB接続定義を記述できるようにします。
これでデータベース(PDO)を使う準備は完了です。
まずは
「http://localhost:8888/api/Slim」と実行すると次のようにJSONが返ります。
ここまでやってみて、Slimが他のフレームワークと比べて圧倒的にシンプルで使いやすいことが分かりました。
個人的にも気に入ったので、ちょっとしたWebアプリの開発ならSlimをドンドン推していきたいですね。
では。
LaravelやCakePHPのようなWebアプリ開発に必要な機能が一通りそろったフレームワークをフルスタックフレームワークと呼ぶのに対し、Slimは軽量フレームワーク(マイクロフレームワーク)と呼ばれます。
フルスタックフレームワークとの違いは、必要最小限の機能だけを有していることによる、学習コストの低さと、軽量さ(ファイルサイズ、実行速度)です。
Slimを使って必要最小限の機能を備えたWebアプリのひな形を作ってみます。
公式サイト
GitHub
目次
プロジェクトの作成
Slim本体はComposerを使ってインストールします。バージョン4が出てますが3系の方が分かりやすかったのでこちらを使います。
まっさらな状態で始めることもできますが、スケルトンと呼ばれる、初期構成のフォルダ・ファイルが用意されたものでプロジェクトを作成します。
composer create-project slim/slim-skeleton:^3.* myapp
できあがるファイル・ディレクトリ構成は次のようになります(一部割愛)。
myapp/
├───logs/
├───public/
│ index.php
│ .htaccess
├───src/
│ dependencies.php
│ middleware.php
│ routes.php
│ settings.php
├───templates/
│ index.phtml
├───tests/
└───vendor
インストールできたらローカルサーバーで実行してみます。
cd myapp
php -S localhost:8888 -t public public/index.php
「http://localhost:8888/」にアクセスするとデフォルトページが表示されます。

サンプルページとフレームワークの処理
「http://localhost:8888/Slim」にアクセスすると、デフォルトで用意されているサンプルページが表示されます。このページの処理を追いかけてフレームワークの詳細をつかみます。

public/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
$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();
フレームワークの起点となるファイルです。.htaccessで静的ファイル以外のURLへのリクエストをこのファイルにリライトします。
内部で以下のファイルを順にインクルードしていて、フレームワークそのものであるAppインスタンスにセット・実行しています。
- src/settings.php
- src/dependencies.php
- src/middleware.php
- src/routes.php
src/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,
],
],
];
アプリケーションの設定を記述するファイルです。エラー表示の有無や、テンプレートやログの配置をここで設定しています。
任意のキーでユーザー独自の設定も作れます。
設定は次のようにフレームワーク内で取得できます。
$container = $app->getContainer();
$settings = $container->get('settings');
src/dependencies.php
<?php
use Slim\App;
return function (App $app) {
$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;
};
};
アプリケーションとコンポーネントの依存関係を設定するファイルです。デフォルトではテンプレートエンジンとログの依存関係が設定してあります。
例えばロガーのコンポーネントを変えてもフレームワーク上は
$container['logger']で変わらずインスタンスにアクセスできるようにする工夫ですね。
src/middleware.php
<?php
use Slim\App;
return function (App $app) {
// e.g: $app->add(new \Slim\Csrf\Guard);
};
リクエスト・レスポンスとMVC処理の間に挟まる処理を記述するファイルです。例えばデバッグツールバーの設定をここで行ったりします。
src/routes.php
<?php
use Slim\App;
use Slim\https\Request;
use Slim\https\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);
});
};
URLから対応する処理へのルーティングを行う部分です。上に書いたものから順にURLのパターンとhttpsメソッドに一致するか見ていき、一致した場合割り当てられた関数の処理が実行されます。
サンプルページは、URLの文字列を$name変数に入れ、
templates/index.phtmlのレンダリングを行っています。
以上がSlim3フレームワークの処理の大まかな流れです。
フルスタックフレームワークに比べシンプルでわかりやすいですね。
カスタマイズする
このままでも、十分ちょっとしたPHPアプリの作成には事足りそうですが、せっかくなのでもうちょっとMVCっぽくしてみます。コントローラーを分離する
デフォルトだとルーティングの中に匿名関数が埋め込まれていて、処理が大きくなると、コードの見通しが悪くなりそうです。コントローラーをクラスとして独立させて、ルーティングではメソッドを呼び出すだけにしてみます。
クラス作成
myappディレクトリの中に新たにcontrollersディレクトリを作成し、その中にHello.phpというクラスファイルを作成します。
<?php
namespace Slim\App\Controllers;
class Hello
{
private $c;
public function __construct($container) {
$this->c = $container;
}
public function index($request, $response, $args)
{
// Sample log message
$this->c->get('logger')->info("Slim-Skeleton '/' route");
// Render index view
return $this->c->get('renderer')->render($response, 'index.phtml', $args);
}
}
コントローラーのメソッドの処理はルーティングの中に書かれていた匿名関数の中身です。
ルーティングからコントローラーのメソッドを呼び出す。
<?php
use Slim\App;
use Slim\https\Request;
use Slim\https\Response;
return function (App $app) {
$container = $app->getContainer();
$app->get('/[{name}]', function (Request $request, Response $response, array $args) use ($container) {
$Hello = new Slim\App\Controllers\Hello($container);
return $Hello->index($request, $response, $args);
});
};
ルーティングの中では先ほど用意したクラスのインスタンス化、メソッド呼び出しを行います。
オートロードの設定
このままでは、コントローラークラスがロードされないので、オートロードされるようcomposer.jsonに記述を追加します。
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/",
"Slim\\App\\Controllers\\": "controllers/"
}
},
追加したら、下記のコマンドでオートローダーをリフレッシュします。
composer dump-autoload
これで、サンプルページにアクセスすると先ほどと変わらない表示ですが、コントローラーは分離されています。
データベースを使う
データベースを使ってみます。DB接続定義を外部ファイルに設定する
環境によって異なるDB接続定義は外部ファイルに記述するのが定石です。先にdotenvを使えるようにして、そこにDB接続定義を記述できるようにします。
composer require vlucas/phpdotenv
composerを使ってdotenvをインストールしたら、srcフォルダに.envファイルを作成し、データベースの情報を記述します。
host=localhost
dbname=test
user=test_user
pass=test_pass
src/settings.phpで.envを読み込み、配列に接続情報をセットします。
<?php
$dotenv = Dotenv\Dotenv::create(__DIR__);
$dotenv->load();
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,
],
// Database
'db' => [
'host' => getenv('host'),
'dbname' => getenv('dbname'),
'user' => getenv('user'),
'pass' => getenv('pass'),
],
],
];
依存関係を設定する
src/dependencies.phpにPDOの依存関係を設定します。
// PDO
$container['db'] = function ($c) {
$db = $c['settings']['db'];
$pdo = new PDO('mysql:host=' . $db['host'] . ';dbname=' . $db['dbname'],
$db['user'], $db['pass']);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
return $pdo;
};
ここではMySQLを使います。これでデータベース(PDO)を使う準備は完了です。
WebAPIを作る
PDOを使う機能をWebAPI形式で作ってみます。まずは
src/routes.phpにルーティングを追加します。
$app->get('/api/[{name}]', function (Request $request, Response $response, array $args) use ($container) {
$Hello = new Slim\App\Controllers\Hello($container);
return $Hello->getJson($request, $response, $args);
});
HelloクラスにgetJsonメソッドを追加します。
public function getJson($request, $response, $args)
{
$sql = <<< SQL
SELECT *
FROM animals
ORDER BY name
SQL;
try {
$stmt = $this->c->get('db')->prepare($sql);
$stmt->execute();
$list = $stmt->fetchAll();
}catch(Exception $e){
$this->c->get('logger')->error($e->getMessage());
}
$name = $request->getAttribute('name');
return $response->withJson([
"name" => $name,
"list" => $list,
], 200);
}
SQLは実行環境に合わせて変更してください。「http://localhost:8888/api/Slim」と実行すると次のようにJSONが返ります。
{
"name": "Slim",
"list": [{
"id": "3",
"name": "bird"
},{
"id": "2",
"name": "cat"
},{
"id": "1",
"name": "dog"
}]
}
ここまでやってみて、Slimが他のフレームワークと比べて圧倒的にシンプルで使いやすいことが分かりました。
個人的にも気に入ったので、ちょっとしたWebアプリの開発ならSlimをドンドン推していきたいですね。
では。







