スピードを求めて軽量フレームワークを採用したけれども一部でLaravelO/Rマッパーが使いたい。
そんなマニアックな案件がごくたまにあります。
LaravelのO/RマッパークラスEloquentは単体で使用することができるので今回はその方法をこちらに記述しておきます。
Eloquent単体のインストール
とりあえず試したい場合はEloquent単体でインストールするeloquent-onlytというパッケージを作ってくれてる方がいるので(感謝)
composerから以下のパッケージをインストールすると使用することができます
eloquent-only
https://packagist.org/packages/mapyo/eloquent-only
・composerコマンドからインストールします
composer require mapyo/eloquent-only
・少し古いバージョンの(illuminate/database)がインストールされるのでバージョンを確認しておきます。
composer show
こちらのバージョンがインストールされています。
lluminate/container v4.2.17 illuminate/database v4.2.17 illuminate/events v4.2.17 illuminate/support v4.2.17 mapyo/eloquent-only 1.0.0 Use only eloquent in laravel nesbot/carbon 1.22.1 A simple API extension for DateTime. symfony/polyfill-mbstring v1.4.0 Symfony polyfill for the Mbstring extension symfony/translation v3.3.6 Symfony Translation Component
・インストールが完了したので試しにデータベースに接続してデータを取得してみましょう
<?php use Mapyo\EloquentOnly\Eloquent; $loader = require('./vendor/autoload.php'); Eloquent::init( array( 'driver' => 'mysql', 'host' => '127.0.0.1', 'database' => 'database', 'username' => 'user', 'password' => 'password', 'port' => 3306, 'collation' => 'utf8_unicode_ci', 'charset' => 'utf8', ) ); class User extends Illuminate\Database\Eloquent\Model { protected $table = 'my_table'; protected $primaryKey = 'user_id'; } $user = User::find(1); var_dump($user->name); $log = Eloquent::getConnection()->getQueryLog(); var_dump($log);
このコードはテーブル【my_table】 から【 user_id = 1 】 のデータを1件検索して、ユーザー名(カラム名: name)を表示します
なおLaravelではデータベースのprimary keyは次のようにすべしと仕様が決まっております
カラム名は「int」 データ型は「unsigned int」で「auto increment」属性
ですので、もしprimarykeyのカラム名が「id」の場合は「$primaryKey = ‘user_id’;」は記述しなくてもOKです。
また他にも以下のプロパティなどがあります。
プロパティ | 説明 | 規定値 |
---|---|---|
$connection | どのDB接続するのか | |
$table | どのtableに接続するのか | モデル名の複数形 |
$primaryKey | 主キーのDBカラム名 | id |
$incrementing | 主キーをオートインクリメントするかどうか | true |
$timestamps | テーブルの作成日時更新日時を自動更新するかどうか | true |
Eloquentの命名パターン
Eloquentの命名は規則として決まっているわけではありませんが(変更可能)
おきまりのパターンを覚えておくとプロジェクト内で作業するときに戸惑いが少ないと思います(と、言いますか知らないと戸惑います。)
・テーブル名、カラム名は 「小文字」「スネークケース」
・テーブル名がusersの場合、Model名はUserになる。
・作成日時カラムは「created_at」
・更新日時カラムは「updated_at」
EloquentのDB操作メソッド
メソッド | 説明 |
---|---|
all() | データ全件取得 |
first() | 最初の1件のみ取得 |
find() | プライマリキーで検索 |
findOrFail() | プライマリキーで検索し見つからない場合例外を投げる |
where() | 検索 |
count() | 件数取得 |
[【Laravel】DBにデータを保存する方法。createとinsertの違いなど – Qiita]
EloquentでのDBリレーション定義
1対1のリレーションを定義してみます。
使用するメソッドはbelongsTo() です。
例)テーブル「dt_matching」に紐付いている「dt_user」テーブル情報を取得する。
取得条件は(dt_matching.work_user_id = dt_user.user_id)
class Matching extends Illuminate\Database\Eloquent\Model { protected $table = 'dt_matching'; protected $primaryKey = 'matching_id'; public function user() { return $this->belongsTo('User','work_user_id','user_id'); } } class User extends Illuminate\Database\Eloquent\Model { protected $table = 'dt_user'; protected $primaryKey = 'user_id'; } $m = Matching::all(); foreach ($m as $k => $v) { print_r($v->user); } $log = Eloquent::getConnection()->getQueryLog(); print_r($log);
実行されたSQLクエリ
結果を見るとこのようなSQLクエリが走ったことがわかります
Array ( [0] => Array ( [query] => select * from `dt_matching` [bindings] => Array ( ) [time] => 102.27 ) [1] => Array ( [query] => select * from `dt_user` where `dt_user`.`user_id` = ? limit 1 [bindings] => Array ( [0] => 1003 ) [time] => 2.68 ) [2] => Array ( [query] => select * from `dt_user` where `dt_user`.`user_id` = ? limit 1 [bindings] => Array ( [0] => 1012 ) [time] => 2.22 ) )
「あれ? LEFT JOIN してないじゃん? 」と思った方は鋭いです。
これがO/Rマッパーの 「n+1問題」です。
https://goo.gl/jX6sG2
n+1 問題を解決する Eloquent Eager Loading
この問題を解決するために with() メソッドが用意されています。
先程のコードを次のように書き換えてみましょう
// $m = Matching::all(); ↓ $m = Matching::with('user')->get();
実行結果
Array ( [0] => Array ( [query] => select * from `dt_matching` [bindings] => Array ( ) [time] => 102.92 ) [1] => Array ( [query] => select * from `dt_user` where `dt_user`.`user_id` in (?, ?) [bindings] => Array ( [0] => 1003 [1] => 1012 ) [time] => 12.74 ) )
SQL文が IN を使用したまとめられました。
大量にデータを取得する時はこちらを使用するといいでしょう。
次回は CodeIgniterから Eloquent を使用する方法を書きたいと思います。