はじめに
過去にSlim 1やSlim 2を使っていて、いくつかのサイトに用いて実戦投入しましたが、最近は主にCakePHPなどに代表されるフルスタックなフレームワークを使っていました。ただフロントエンドがReactやVueなどを用いることが多くなって、バックエンド側もAPIサーバで十分という場合も多く、フルスタックフレームワークはスペックオーバーに感じる今日この頃。
そこでシンプルなWEBサイトやAPIサーバ用にマイクロフレームワークのSlim 3を用いてMVCぽい感じでアプリケーションを作成できる雛形を作ってみました。
ちなみにSlimの名前はテンプレートエンジンのSlimと被っていて、あちらの方がメジャーなのでググラビリティが低いですね。
使用コンポーネント
- Eloquent ORM (モデル)
- PHP-View (ビュー)
- Pimple (DIコンテナ)
- Monolog (ログ)
- PHPUnit (テスト)
インストール
新規にプロジェクトを作るのはComposerを使います。
composer create-project m92o/slim-mvc-skeleton [my-app-name]
サンプルコードも含まれているのすぐに動きます。
テストを動かす場合は、[my-app-name]ディレクトリに移動して
composer test
ビルトインサーバでアプリを動かす場合は
composer start
で、 http://localhost:8080/ にアクセスしてみてください。
ディレクトリ構成
├── app
│ ├── configs
│ │ ├── dependencies.php
│ │ ├── middleware.php
│ │ ├── routes.php
│ │ └── settings.php
│ ├── controllers
│ │ ├── AppController.php
│ │ └── HomeController.php
│ ├── libs
│ │ ├── Facade.php
│ │ └── Log.php
│ ├── models
│ │ ├── AppModel.php
│ │ └── User.php
│ ├── views
│ │ └── home.phtml
│ ├── bootstrap.php
│ └── environment.php
├── containers
├── db
├── logs
├── public
│ └── index.php
├── tests
│ └── Functional
│ ├── BaseTestCase.php
│ └── HomepageTest.php
├── vendor
├── composer.json
├── docker-compose.yml
└── phpunit.xml
Slim公式のslim-skeletonを使ったことある人には見覚えのあるファイルもありますね。/app/configsにあるファイルは、ほぼslim-skeletonのままです。MVCに合わせて models / controllers / views のディレクトリが用意されています。それ以外は libs に入れる感じ。
/containersはDockerコンテナの設定などです。
使い方
サンプルコードが含まれているので、それを見ながら説明します。
設定
環境設定
DB等の設定は/app/configs/settings.phpに書きます。
環境変数SLIM_ENVの値により使用する設定を切り替えるようになっています。SLIM_ENVが未設定の場合はdevelopmentが使用されます。
environments = [
'production' => [
'db' => [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database',
'username' => 'user',
'password' => 'password',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => ''
]
]
];
ルーティング
ルーティングの設定は/app/configs/routes.phpです。
<?php
use Controllers\HomeController;
// Routes
$app->get('/', HomeController::class . ':index');
/ にGETメソッドでアクセスが来たら、HomeControllerクラスのindexメソッドを呼び出すという設定になります。ルーティング設定は全て自分で書く必要があります。
ルーティングの詳細はSlimのドキュメントを参照してください。
https://www.slimframework.com/docs/v3/objects/router.html#container-resolution
コントローラ
コントローラは、AppControllerを継承して書いていきます。routes.phpで設定したメソッドを実装します。
<?php
namespace Controllers;
use Slim\Http\Request;
use Slim\Http\Response;
use Controllers\AppController;
use Models\User;
use Libs\Log;
class HomeController extends AppController {
public function index(Request $request, Response $response, array $args) {
$user = User::find(1);
//Log::info('User', ['fullName' => $user->fullName]);
return $this->view->render($response, 'home.phtml', ['user_name' => $user->fullName]);
}
}
Userはモデルです。ログはLog::info()
のようにスタティックメソッドとして呼び出し可能です。(LaravelのFacadeを真似てある)
ログの使い方はMonologのドキュメントを参照にしてください。
https://github.com/Seldaek/monolog
$this->view->render()
でビューを呼び出します。
モデル
モデルはAppModelを継承して書いていきます。AppModelはEloquent ORMを継承したものです。
<?php
namespace Models;
use Models\AppModel;
class User extends AppModel {
}
今回は中身が空ですが、ここにビジネスロジックを書く形です。
クラス名(単数形)の複数形がテーブル名になっている必要があります。レールを外れる場合は protected $table = 'table_name';
のようにクラス変数に記述します。
詳しくはLaravelのドキュメントを参照してください。
https://laravel.com/docs/5.7/eloquent
ビュー
テンプレートエンジンにはPHP-Viewを使用していますので、ただのPHPファイルです。HTMLにPHPのコードを埋め込みます。
Hello, <?= $user_name ?>!
コントローラで呼び出した$this->view->render()
の第3引数の連想配列が、ビューに渡された変数になります。(連想配列のuser_nameキーの値が、$user_name
で取り出せる)
テスト
テストはBaseTestCaseを継承して書いていきます。PHPUnitです。
<?php
namespace Tests\Functional;
class HomepageTest extends BaseTestCase {
/**
* Test that the index route with optional name argument returns a rendered greeting
*/
public function testGetHomepageWithGreeting() {
$response = $this->runApp('GET', '/');
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('Hello, John Smith!', $response->getBody());
}
}
$this->runApp()
でURLにアクセスして、戻ってきたレスポンスの中身を確認します。
まとめ
以上、ざっくりとした説明でした。
マイクロフレームワークを用いて、単純なMVCフレームワークを作ってみました。フルスタックフレームワークの便利さはありませんが、RESTでJSONを返す程度のAPIサーバならこの程度で十分そうです。