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



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

[laravel製軽量フレームワーク Lumenを試してみる](http://qiita.com/yaaamaaaguuu/items/f42f1127c96f44cb836f)の続き的な感じです。

記事を読むのが面倒な方は、[github](https://github.com/shouhei/lumen-memo)と[gists](https://gist.github.com/shouhei/959aacadbd3b258a5f9d)を見たらなんとかなると思います。

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

# 趣旨

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```があるのでそれをコピーして書き直す

```diff
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```で上手く実行できず、エラーの手前で設定を出力したら以下のとおりになっていた。


```php
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にはテーブルを削除するコードを入れておく。

```diff
<?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
<?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>
```

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

```diff
<?php namespace App\Http\Models;

use Illuminate\Database\Eloquent\Model;

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

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

![localhost_8000_posts.png](https://qiita-image-store.s3.amazonaws.com/0/10992/a2f145d0-6324-242f-fe37-559657b3b7b8.png "localhost_8000_posts.png")

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

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

```diff

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

```

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

# 終わりに

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