a

https://x.com/Akr4mKhan/status/1893299711651582358
toBase()
でメモリ使用量を削減しよう
大規模データを扱うときは Laravel で大規模なデータを扱う場合、Eloquent モデルをそのまま取得するとメモリ使用量が大きくなりがちです。これは「モデルのインスタンス化(hydration)」が行われ、全てのフィールドやリレーションなどが読み込まれるためです。
そこで役立つのが、toBase()
メソッドです。toBase()
を使うと、データベースから取得したレコードをシンプルな PHP オブジェクトとして扱うことができ、余分な Eloquent の機能を省略できるため、メモリの使用量を抑えられます。
使い方
<?php
use App\Models\Post;
// 大規模データをシンプルなPHPオブジェクトとして取得
$posts = Post::toBase()->get();
このように toBase()
を挟むことで、返却されるのは Illuminate\Support\Collection に格納された、stdClass オブジェクトの一覧になります。Eloquent モデルではなくなるため、通常のモデルメソッド(例: $post->save()
など)は利用できませんが、データのエクスポートや集計など、「読み取り専用」で十分な場面では非常に有効です。
どんなときに使う?
-
CSV や Excel へのエクスポート
大量のレコードを一気にエクスポートする場合、フルモデルを使うとメモリを圧迫しやすくなります。toBase()
を活用すれば、必要最低限の情報だけを取得して出力できます。 -
バッチ処理
定期的に大きなテーブルを処理するバッチタスクなどで、モデルが不要なケースは多々あります。シンプルなオブジェクトの方が高速かつ省メモリで済むことがあります。
実装例:CSV エクスポート
下記は、全ての posts
テーブルのレコードを CSV としてエクスポートするイメージ例です。データ取得部分で toBase()
を利用しています。
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Post;
class ExportPostsCommand extends Command
{
protected $signature = 'export:posts';
protected $description = 'Export all posts to CSV';
public function handle()
{
// 大量データをシンプルに取得
$posts = Post::toBase()->get();
$filePath = storage_path('app/public/posts.csv');
$file = fopen($filePath, 'w');
// ヘッダ行(例)
fputcsv($file, ['id', 'title', 'content', 'created_at']);
foreach ($posts as $post) {
// $post は stdClass
fputcsv($file, [
$post->id,
$post->title,
$post->content,
$post->created_at
]);
}
fclose($file);
$this->info("Exported to {$filePath}");
}
}
-
toBase()
を使うことで、モデルインスタンスではなく、stdClass のオブジェクトが返ってきます。 - ループの中で
$post->id
のようにアクセスできますが、$post->save()
などのモデルメソッドは利用できません。 - もしレコード数が非常に多い場合は、
chunk()
メソッドなどを組み合わせると、よりメモリ効率が高まります。
まとめ
toBase()
は大規模データを扱う際のメモリ削減に有効- Eloquent モデルが不要な場面(読み取り専用)で特に威力を発揮
- CSV エクスポートやバッチ処理などで便利に使える
データ量が多く、Eloquent モデルとしての機能が不要な場面では、ぜひ toBase()
を活用してみてください。メモリ使用量の削減やパフォーマンス向上に役立ちます。