LaravelのEloquentORMを調べてみた

基本は[公式ドキュメント](https://readouble.com/laravel/5.3/ja/eloquent.html)を参照

上からコピペしていけば、実行できるように書きました。手を動かすこと推奨です。

### テーブル作成
---

```sql
drop table blogs;
drop table blog_comments;

CREATE TABLE `blogs` (
    `id` INT(10) UNSIGNED NOT NULL,
    `name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
    `zip_code` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
    PRIMARY KEY (`id`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;

CREATE TABLE `blog_comments` (
    `blog_id` INT(10) UNSIGNED NOT NULL,
    `comment` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
    `zip_code` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci'
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;
```
zip_code？と、思った方。スネークケースがほしかったのです。。。

### Eloquent ORMを継承したクラスのひな形作成
---
```bash
php artisan make:model Blog
php artisan make:model BlogComment
```

### 出来上がったクラスに多少手を加えたバージョン
---

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Blog extends Model
{
    protected $table = 'blogs';
    protected $primaryKey = 'id';
    public $timestamps = false;
    
    public function comments()
    {
        return $this->hasMany('App\BlogComment');
    }
}

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class BlogComment extends Model
{
    protected $table = 'blog_comments';
    protected $primaryKey = 'blog_id';
    public $timestamps = false;

    public function blog()
    {
        return $this->belongsTo('App\Blog');
    }    
}
```

### LaravelのREPLを使って、データ流し込み
---

```php
php artisan tinker

DB::table('blogs')->delete();
DB::table('blog_comments')->delete();

DB::table('blogs')->insert(['id' => 1, 'name' => 'name1', 'zip_code' => '111-0001']);
DB::table('blogs')->insert(['id' => 2, 'name' => 'name2', 'zip_code' => '121-0001']);
DB::table('blog_comments')->insert(['blog_id' => 1, 'comment' => 'comment11', 'zip_code' => '111-0011']);
DB::table('blog_comments')->insert(['blog_id' => 1, 'comment' => 'comment12', 'zip_code' => '111-0012']);
DB::table('blog_comments')->insert(['blog_id' => 1, 'comment' => 'comment13', 'zip_code' => '111-0013']);
DB::table('blog_comments')->insert(['blog_id' => 2, 'comment' => 'comment21', 'zip_code' => '121-0021']);
DB::table('blog_comments')->insert(['blog_id' => 2, 'comment' => 'comment22', 'zip_code' => '121-0022']);
DB::table('blog_comments')->insert(['blog_id' => 2, 'comment' => 'comment23', 'zip_code' => '121-0023']);
```

ここまでで、下準備おわり。

### 実際に使ってみる
---

```php
php artisan tinker

// blogsテーブルデータ全取得
$blogs = App\Blog::all();

// blog_commentsテーブルデータ全取得
$blogComments = App\BlogComment::all();

// Blogの子テーブル情報取得（hasMany）
$comments = App\Blog::find(1)->comments;

// Blogの情報に子テーブルの情報も付加して、さらにjsonにしたバージョン
$blogWithComment = App\Blog::with('comments')->find(1)->toJson();
=> {"id":1,"name":"name1","zip_code":"111-0001","comments":[{"blog_id":1,"comment":"comment11","zip_code":"111-0011"},{"bl
og_id":1,"comment":"comment12","zip_code":"111-0012"},{"blog_id":1,"comment":"comment13","zip_code":"111-0013"}]}

// BlogCommentの親テーブル情報取得（belongsTo）
$blogComment = App\BlogComment::find(1); // この時点で親の情報はSQLしてない。遅延ローディングらしい。
$blogComment->blog; // ここでSQLして、Blog情報を取ってきている。It's Magical Code.

// ３つ以上のブログコメントを持つblogの取得
$blog = App\Blog::has('comments', '>=', 3)->get();
=> Illuminate\Database\Eloquent\Collection {#703
     all: [
       App\Blog {#720
         id: 1,
         name: "name1",
         zip_code: "111-0001",
       },
     ],
   }

// mysqlのクエリログとか見ていないと、Eagerローディングの違いはわからないです。
// Eagerローディング無し（belongsTo）
$blogComments = App\BlogComment::all();
foreach ($blogComments  as $blogComment) {
    echo $blogComment->blog->name;
}

// Eagerローディング有り（belongsTo）
$blogComments = App\BlogComment::with('blog')->get();
foreach ($blogComments  as $blogComment) {
    echo $blogComment->blog->name;
}
```

### まとめ
---

非効率なクエリとかあるかなぁ？と、クエリログ見ながら実行していたのですが、大丈夫そうでした。
ORMのコードを見ているとSQLがどうなるか？分からないものが多いですが、このORMは割とシンプルなほうかなぁと思いました。ただ、クラスの中身をしっかりと知らない状態では使えないので、学習コストはあるなぁという印象でした。

あ、mysqlのログ出す方法は[windowsでmysql5.7をzipインストールする](http://qiita.com/daijinload/items/cf3e2e548f5008973140)を参照してみてください。（しょぼい設定だし、よく見るとwindowsって書いてありますが、iniファイルの部分だけなら変わらんですよ。たぶん。）