Laravel製 軽量フレームワーク Lumen ORMとMigrationを触ってみる


「鉄は熱いうちに打て」というやつです。

laravel製軽量フレームワーク Lumenを試してみるの続き的な感じです。

記事を読むのが面倒な方は、githubgistsを見たらなんとかなると思います。

今回の完成形のコードと設定ファイルを置いてます。

趣旨

LumenでORMとMigrationを使ってみる

方向性

  • 書きっぱなしのメモアプリを目指す。
  • スキーマはid, body, 日付くらいで良いかな
  • DBはSQLiteを使います。

前回のおさらい

一からプロジェクトを作りたいので以下のコマンドを叩く。

lumen new memo

DB用のディレクトリを作成

ドキュメントの引用

If you would like to use database migrations with Lumen, you should run the php artisan make database Artisan command. This command will create a database directory in your project root which contains migrations and seeds directories.

For further information on how to create database tables and run migrations, check out the Laravel documentation on the schema builder and migrator.

意訳:php artisan make databaseでDB用のディレクトリとか作れるけど、詳しくはLaravelのドキュメントとか見てね。

叩くと一番上の階層にdatabasesディレクトリが作成されて、以下の様なディレクトリ構成になる

.
├── app
│   ├── Console
│   ├── Exceptions
│   ├── Http
│   ├── Jobs
│   └── Providers
├── artisan
├── bootstrap
│   └── app.php
├── composer.json
├── composer.lock
├── database
│   ├── migrations
│   └── seeds
├── phpunit.xml
├── public
│   └── index.php
├── readme.md
├── server.php
├── storage
│   ├── app
│   ├── framework
│   └── logs

Laravelのドキュメントを読んでSQLiteを設定する

Laravelではapplication/config/database.phpで設定して、storage/databasesフォルダに適切な名前のファイルを設置したらOKと書いてある。

Lumenではどうなるか試した所結果

  1. DBの設定は.envで設定する
  2. DBファイルは同様に設置する

以下は試行錯誤の結果

.env

トップディレクトリに.env.exampleがあるのでそれをコピーして書き直す

APP_ENV=local
APP_DEBUG=true
APP_KEY=SomeRandomKey!!!

APP_LOCALE=en
APP_FALLBACK_LOCALE=en

+DB_CONNECTION=sqlite
-DB_CONNECTION=mysql
-DB_HOST=localhost
-DB_DATABASE=homestead
-DB_DATABASE=homestead
-DB_USERNAME=homested
-DB_PASSWORD=secret
+#DB_HOST=localhost
+#DB_DATABASE=homestead
+#DB_DATABASE=homestead
+#DB_USERNAME=homested
+#DB_PASSWORD=secret

CACHE_DRIVER=memcached
SESSION_DRIVER=memcached
QUEUE_DRIVER=database

# FILESYSTEM_DRIVER=local
# FILESYSTEM_CLOUD=s3

# S3_KEY=null
# S3_SECRET=null
# S3_REGION=null
# S3_BUCKET=null

# RACKSPACE_USERNAME=null
# RACKSPACE_KEY=null
# RACKSPACE_CONTAINER=null
# RACKSPACE_REGION=null

また.envを書いた場合、bootstrap/app.php内に書いてある、Dotenv::load()のコメントアウトを外しなさい書いてあるので外します。

DBファイル

今回はstorage/database.sqliteという形で設置した。tocuhコマンドで作ればok

結果論として

.envの設定が有効にならない気がする。
最初に想定していた設定

DB_CONNECTION=sqlite
DB_DATABASE=memo.sqlite

というのも最初はmemo.sqliteというファイル名で実行するつもりだったが、後のmigrate:installで上手く実行できず、エラーの手前で設定を出力したら以下のとおりになっていた。

array(4) {
  ["driver"]=>
  string(6) "sqlite"
  ["database"]=>
  string(64) "/path/to/memo/storage/database.sqlite"
  ["prefix"]=>
  string(0) ""
  ["name"]=>
  string(6) "sqlite"
}

自分にLaravelの知識が対して無いためなのか、それともドキュメントの見落としか、バグなのかは定かで無いのですが、時間が有るときにコードを追ってみます。

明らかに間違っていれば、どなたかツッコミをお願いします。

スキーマの設定

Laravelのドキュメントを見つつ、マイグレーションでいい感じにやっていきます。

まずマイグレーションをしていくよ!ということを宣言します。

php artisan migrate:install

うまくいくと以下のようにコメントが出る

Migration table created successfully.

で、実際にマイグレーションファイルをつくる。

このコマンドで生成されるファイルはdatabase/migrationsに設置される

php artisan make:migration create_posts_table

生成されたmigrationファイルを編集する。

upには今回欲しいid,contentと時間を生成するコードを記述。
downにはテーブルを削除するコードを入れておく。

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration {

        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
+           Schema::create('posts', function(Blueprint $table){
+                $table->increments('id');
+                $table->text('body');
+                $table->timestamps();
+        });
        }

        /**
         * Reverse the migrations.
         *
         * @return void
         */
        public function down()
        {
+            Schema::drop('posts');
        }

}

で、実行の前にbootstrap/app.phpを編集して、以下二行をコメントイン

#もしかしたらEloquentはこの段階では不要かもしれませんが
$app->withFacades();
$app->withEloquent();

実行

php artisan migrate

うまくいくと

Migrated: ~~

ORMの設定

Eloquentと言うやつを使う。まずはファイルの設置から。

今回はapp/Http/Modelsというディレクトリを作成し、そこにPost.phpを設置した。

ネームスペースの宣言と、Illuminate\Database\Eloquent\Modelの継承が必要。またクラス変数$tablesにテーブル名を設定

<?php namespace App\Http\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model {
    protected $table = 'posts';
}

ORMの利用

routes.phpは、/postsにgetしたら一覧と登録フォーム、postしたらメモの内容を登録してリダイレクトという形でコードを書き換える

#先ほど作成したPostを利用するよ
use App\Http\Models\Post;

 $app->get('/', function() use ($app) {
    return $app->welcome();
});

$app->get('/posts',function() use($app){
    #resoureces/posts/index.blade.phpを参照
    # 変数として、postsに postsテーブルからの全てのデータを代入
    return view('post/index',['posts'=>Post::all()]);
 });

$app->post('/posts',function() use($app){
    # リクエスト内容を登録
    Post::create(Request::all());
    #LaravelのRidirectクラスとは異なり、redirect関数を利用する
    return redirect('/posts');
});

また/postsの見た目を軽く作る

以下は/resources/posts/index.blade.php

<form action="/posts" method="post">
  <input type="text" name="body" placeholder="メモ欄">
  <input type="submit" value="登録">
</form>
<ul>
  <li>メモ一覧</li>
  @foreach ($posts as $post)
    <li>{{$post->body}}</li>
  @endforeach
</ul>

最後にPostcreateメソッドを利用する際に、どの値を利用するかの設定を書き足す

<?php namespace App\Http\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model {
    protected $table = 'posts';
+    #保存時の引数のkeyとしてbodyは許可するよ
+    protected $fillable = array('body');
}

以上の様にコードを書きlocalhostで動かして試すと以下の様な画面になると思う。

最後の設定

おそらく、本記事にそってコードを書いていると、連続でpostが出来ない。

理由はキャッシュエンジンにmemcachedが設定されているためなので、.envを書き換える必要がある


-CACHE_DRIVER=memcached
-SESSION_DRIVER=memcached
+CACHE_DRIVER=file
+SESSION_DRIVER=file

書き換えることで、連続でpostすることも可能になる。
めんどうなので削除とかは書かないが、ドキュメントを見たらすぐに書けると思う。

終わりに

Laravelの知識が無いので不正確な部分もあるかと思います。
指摘をしていただければできるだけ早く修正をするのでよろしくお願い致します。