こんにちは、Nakaです。

Laravel の DB Facade は非常に柔軟で、シンプルな記述でデータベース操作を書けるのが大きな魅力です。 DB::transaction()DB::table() なども、特に意識せず使っている方は多いのではないでしょうか。一方で、複数のデータベース接続を扱うプロジェクトでは、意図しないデフォルトコネクションへのアクセスが紛れ込みやすい、という落とし穴があります。

本記事では、実際のプロジェクトで発生した

について紹介します。「PHPStan のカスタムルールをどう実務に使うか」という観点でも、一つの具体例として参考になれば幸いです。


複数 DB 環境でデフォルト接続が招く事故

今回のプロジェクトでは、以下のように用途別に複数のDBコネクションを持っていました。

Laravelの config/database.php ではdefaultmaster に設定されています。

'default' => env('DB_CONNECTION','master'),

この状態で、次のようなコードを書くとどうなるでしょうか。

DB::transaction(function () use ($user, $userItem) {
    $user->save();     // $userは'user'コネクションのEloquentモデル
    $userItem->save(); // $userItemは'user'コネクションのEloquentモデル
});

一見すると問題なさそうですが、この transactionmaster コネクションに対して張られます。しかし、本来この処理は user コネクション に対して行うべきものでした。

正しくは、以下のように明示的に接続先を指定する必要があります。

DB::connection('user')->transaction(function () use ($user, $userItem) {
    $user->save();
    $userItem->save();
});