LoginSignup
5
7

More than 5 years have passed since last update.

Laravel EloquentのEager LoadingでWrite接続を使用する

Last updated at Posted at 2017-02-06

小ネタです。

master/slave構成を取っているDBを使用する場合、LaravelではRead/Write接続を設定して
Connectionの切替を行うことが多いかと思われます。

Read/Write接続の参考:https://readouble.com/laravel/5.3/ja/database.html

たまに、レプリケーションの遅延等々を考えた際に、処理によっては必ずWrite接続(master)を
使用してクエリを実行したいケースが発生することはないでしょうか。

自分はそんなケースがあったので、Write接続を使用するように、以下のようなコードを書きました。
※ 受注(Order)情報を取得する、というケースのイメージになります。

Order.php抜粋
...中略

class Order extends Model
{

...中略

    protected $table = 'orders';

...中略

    public function details()
    {
        return $this->hasMany(OrderDetail::class, 'order_code', 'order_code');
    }

}
Write接続を使用して検索する
$order = Order::useWritePdo()->find($orderId);

useWritePdoを呼び出すことで、Write接続を使用して検索クエリが実行されます。

接続取得の切り分けは、

Illuminate\Database\Connection#select → getPdoForSelect

の辺りで実装されていたので、そちらを見るとよく分かるかなと思います。

ここまではすぐできるのですが、上記の例で受注明細(OrderDetail)をEager Loadingで取得したい場合、かつ
Write接続で検索したい場合はどうすればよいのだろう?というのが今回ちょっと詰まったところです。

単純にwithを使うとこんな感じになって、

with使う
$order = Order::useWritePdo()->with('details')->find($orderId);

以下2本のクエリが実行されます。

実行されるクエリ
select * from `orders` where `orders`.`id` = ? limit 1
select * from `order_details` where `order_details`.`order_code` in (?)

これでよさそうな感じがしますが、Illuminate\Database\Connection#selectにデバッグ張って見てみると、
2本目のクエリはRead接続を使用して実行されていることが確認できました。
※ Illuminate\Database\Connection#select実行時に、接続切り分けの引数「$useReadPdo」がtrueになっている。
親の検索で使用されたBuilderと、違うインスタンスが使用されている?ようです。

今回は、2本目の検索もWrite接続を使用したかったのです。

色々調べてみたのですが、withのcallbackでEager Loadingで使用されるBuilderインスタンスが
触れるということだったので、そちらでuseWritePdoを呼び出してWrite接続を使用することにしました。

Eager Loading時にWrite接続を使用する
$order = Order::useWritePdo()->with(['details' => function ($query) {
    /** @var \Illuminate\Database\Query\Builder $query */
    $query->useWritePdo();
}])->find($orderId);

これで、Eager Loading時のクエリもWrite接続を使用することが確認できました。
ちょっとスマートじゃない感もあるので、、、よりよいやり方があれば教えてください。

環境

Laravel Framework 5.2.45
PHP 7.0.3

参考ページ

以下を参考にさせていただきました。
ありがとうございました。

5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7