基本は公式ドキュメントを参照
上からコピペしていけば、実行できるように書きました。手を動かすこと推奨です。
テーブル作成
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を継承したクラスのひな形作成
php artisan make:model Blog
php artisan make:model BlogComment
出来上がったクラスに多少手を加えたバージョン
<?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 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 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.
// 3つ以上のブログコメントを持つ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インストールするを参照してみてください。(しょぼい設定だし、よく見るとwindowsって書いてありますが、iniファイルの部分だけなら変わらんですよ。たぶん。)