私が所属している会社の業務でデータの抽出処理を実装するということになったのですが、その抽出条件が多数のテーブルとそのカラムに跨っているという物でした。
その実装方法を色々試している中、「なぜこれができないんだ」と困った話について書いていきたいと思います。
LaravelのEloquentでは、Modelクラス内でリレーションを設定することで、with
メソッドを用いて関連するモデルの情報を同時に取得するということができます。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class SomeTable extends Model
{
public function otherData()
{
return $this->hasOne('App\OtherData', 'otherdata_id');// hasManyも同様の記述
}
}
App\SomeTable::with(['otherData']);
// SomeTableのデータと共に、対応するOtherDataのデータも同時に取得できる
この時、OtherData
の内一部のカラムの情報のみが欲しいという場合、そのカラムを記述することで取得するデータを絞ることができます。
App\SomeTable::with(['otherData:otherdata_id,another_column']);
// 対応するOtherDataのデータの内、主キーとanother_columnのみが取得される
また、OtherData
の内特定条件を満たすもののみを取得するということもできます。
App\SomeTable::with([
'otherData' => function($query) {
$query->where('another_column', '<', 10);
}
]);
// 対応するOtherDataのデータの内、another_columnが10未満のもののみが取得される
今回実装したい抽出処理では多数のテーブルに必要な情報が跨っているものの、その内実際に利用するカラムは僅かです。そのため、PHP側での処理が重くならないように次のようなコードを書いてみました。
App\SomeTable::with([
'otherData:otherdata_id,another_column' => function($query) {
$query->where('another_column', '<', 10)
}
]);
// 期待した通りには動かない
改めて考えてみたところ、カラム指定を行わないwith
で取得するオブジェクトはModelクラスを継承しているものになっていたのですが、カラム指定をすると単なるCollectionクラスのオブジェクトになっていました。なので、カラム指定をした場合Modelに対するwhere
ではなく、Collectionに対するwhere
として動作してしまい、期待した動作にはならなかったのではないかと考えています。
今回の抽出処理の実装については、ひとまず愚直にテーブルをjoin
することで実装することにしました。何かいい方法があるとなればコメント等宜しくお願い致します。