6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Slim3_PHPAdvent Calendar 2018

Day 24

Slim Framework 3 MVC Skeleton Application

Last updated at Posted at 2018-12-23

はじめに

過去に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が使用されます。

settings.php
environments = [
    'production' => [
        'db' => [
            'driver' => 'mysql',
            'host' => 'localhost',
            'database' => 'database',
            'username' => 'user',
            'password' => 'password',
            'charset'   => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix'    => ''
        ]
    ]
];

ルーティング

ルーティングの設定は/app/configs/routes.phpです。

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で設定したメソッドを実装します。

HomeController.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を継承したものです。

User.php
<?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のコードを埋め込みます。

home.phteml
Hello, <?= $user_name ?>!

コントローラで呼び出した$this->view->render()の第3引数の連想配列が、ビューに渡された変数になります。(連想配列のuser_nameキーの値が、$user_nameで取り出せる)

テスト

テストはBaseTestCaseを継承して書いていきます。PHPUnitです。

HomepageTest.php
<?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サーバならこの程度で十分そうです。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?