【Laravel】Eloquentのクエリビルダを使いながらクエリ結果はstdClassにする方法の紹介

  • 2025年4月11日
  • 2025年4月11日
  • Laravel

LaravelでDB(データベース)からデータを取得する際その使い道によってはEloquentモデルのインスタンスを作成する必要がない場合があります。例えばCSVのダウンロード機能などではデータの整形だけできれば十分でモデルに紐づくメソッドなどは使いません。

こういった場合Eloquentモデルのインスタンス化は余計な処理となり処理速度やメモリ使用量の面でデメリットになります。

モデルのインスタンス化を避ける方法としては最初から\DB::query()のようにモデルから離れたクエリビルダ機能を使うのも手です。しかしこの方法ではEloquentに紐づいて定義されたグローバルスコープなどの機能を活かすことができません。

そこで便利なのが、Eloquentのクエリビルダを使いながら、結果はEloquentモデルではなくstdClassのインスタンスとして取得する方法です。

具体的には、toBase()メソッドを使用します。

// 全件取得(結果は stdClass のコレクションになる)
$users = User::query()->toBase()->get();

この方法を使うことで、Eloquentのクエリビルダの書きやすさをそのままに、モデルのインスタンス化を避けた軽量な処理が可能になります。

以下はCSVをchunkしながら出力する処理の例です。モデルを使うよりもメモリを使わず高速です。

public function downloadCsv()
{
    $headers = [
        'Content-Type' => 'text/csv',
        'Content-Disposition' => 'attachment; filename="users.csv"',
    ];

    return response()->stream(function () {
        $handle = fopen('php://output', 'w');

        // ヘッダー行
        fputcsv($handle, ['ID', '名前', 'メールアドレス']);

        User::query()
            ->toBase()
            ->orderBy('user_id')
            ->chunk(1000, function ($users) use ($handle) {
                foreach ($users as $user) {
                    fputcsv($handle, [
                        $user->user_id,
                        $user->name,
                        $user->email,
                    ]);
                }
            });

        fclose($handle);
    }, 200, $headers);
}

こんな感じでtoBase()を使えば、モデルを介さずにEloquentのスコープやクエリビルダの機能を活かしたまま軽量にデータを処理することができます。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG