PHPフレームワークLaravelのO/RマッパークラスEloquentを単体で使用する

スピードを求めて軽量フレームワークを採用したけれども一部で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のDB操作メソッド

メソッド 説明
all() データ全件取得
first() 最初の1件のみ取得
find() プライマリキーで検索
findOrFail() プライマリキーで検索し見つからない場合例外を投げる
where() 検索
count() 件数取得

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 を使用する方法を書きたいと思います。

 

 

PHPフレームワークLaravelのO/RマッパークラスEloquentを単体で使用する
Tagged on:             

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA