.../articles/

Laravelのfactoryのinsertを改善してテストの効率化をした

Laravelのfactoryによるデータ作成を効率化させて、seederで時間がかかっていた部分を改善した内容について書きました。

環境
  • Laravel 5系

Laravelのfactoryは強力で、階層構造を持ったデータも直感的な記述で作成することができます。ですが、1件ずつinsertが発行されてしまう為、少し注意が必要です。

// usersを5件つくる
factory(User::class, 3)
->create()
->each(function (User $user) {
    // ordersを5件つくる
    factory(Order::class, 5)
    ->create(['user_id' => $user->id])
    ->each(function (Order $order) {
        // order_detailsを10件つくる
        factory(OrderDetail::class, 10);
    });
});

このコードでは、3×5×10で150回のinsertが作成されてしまい、パフォーマンス的にあまりよろしくありません。
このような場合、factoryにはinstanceのみ生成するmakeという関数があるので、これをinsertと合わせて使います。

// usersを3件追加
$users = factory(User::class, 3)->make();
User::query()->insert($users->toArray());
//insertしたuserをfind
$users = User::query()->orderBy('created', 'desc')->limit(3)->get(); 
$users->each(function (User $user){

    // ordersを5件作成
    $orders = factory(Order::class, 5)->make(['user_id' => $user->id]);
    Order::query()->insert($orders->toArray());
    //insertしたorderをfind
    $orders = Order::query()->orderBy('created', 'desc')->limit(5)->get(); 

    $orders->each(function(Order $order){
        // order_detailsを10件作成
        $orderDetails = factory(OrderDetail::class, 10)->make([
            'user_id' => $user->id, 'order_id' => $order->id
        ]);
        OrderDetail::query()->insert($orderDetails->toArray());
    });
});

コードの見通しが悪くなるのが悔しいですが、SQLの実行回数は150回から、23回(1+1+3*(2+5*(1)))まで減らすことができました。

上のコードを書いた所、「この方が少なくなるよ」とレビューをいただきました。以下のコードでは、SQLの実行回数は合計5回になります。

<?php 

// Userを3件作成
$users = factory(User::class, 3)->make();
User::query()->insert($users->toArray());
$users = User::query()
    ->orderBy('created', 'desc')
    ->limit(3)
    ->get(); 

// Userに紐づくOrdersを作成
$orders = [];
$users->each(function (User $user){
    $orders[] = factory(Order::class, 5)
        ->make(['user_id' => $user->id])
        ->toArray();
});
Order::query()->insert($orders);

// 作成した、Userに紐づくOrderを取得をして、
// そのOrderに紐づくOrderDetailを作成
$orderDetails = []
$orders = Order::query()
    ->whereIn('user_id', $users->pluck('user_id')
    ->toArray())
    ->get();
$orders->each(function(Order $order){
    $orderDetails[] = factory(OrderDetail::class, 10)
        ->make(['user_id' => $user->id, 'order_id' => $order->id])
        ->toArray());
});
OrderDetail::query()->insert($orderDetails);

また、make関数は、配列で準備しているデータをfacotryを通してinsertしたい場合にも使うことができます。

$vegetables = [
    ['vegetable_group' => 1, 'name' => '大根'],
    ['vegetable_group' => 1, 'name' => 'かぼちゃ'],
    ['vegetable_group' => 1, 'name' => 'さつまいも'],
    ['vegetable_group' => 2, 'name' => 'にら'],
    ['vegetable_group' => 2, 'name' => 'レタス'],
    ...
    ...
    ['vegetable_group' => 9, 'name' => 'えのき'],
    ['vegetable_group' => 9, 'name' => 'しめじ'],
];

$insertVegetables = [];
foreach($vegetables as $v){
    $insertVegetables[] = factory(Vegetables::class)->make($v)->toArray();
}
Vegetables::query()->insert($insertVegetables);

さいごに

テストの実行に時間がかかっているプロジェクトがあり、改善したい思いチューニングした内容を記事にしました。大規模なプロジェクトはどんな風にテストデータ設計しているか知りたいなと思いました。

.../articles/

Articles

記事

AWS AmplifyにmonorepoのNext.js(App Router)をデプロイする

AWS AmplifyにmonorepoのNext.js(App Router)をデプロイする

monorepo管理しているNext.jsをAmplifyにデプロイしようとした際にいくつか躓く内容があったのでまとめておきます。

リモートワーク・オンライン会議でも、スムーズに制作を進めるために大切なこと[資料編]

リモートワーク・オンライン会議でも、スムーズに制作を進めるために大切なこと[資料編]

コロナ禍の影響により、リモートワークの導入をおこなっている制作会社も多く、実際に弊社でも導入しています。

売れるECサイトデザインを作るために。参考にしたいおしゃれな事例の探し方。

売れるECサイトデザインを作るために。参考にしたいおしゃれな事例の探し方。

売れるECサイトのデザインは、「この形式」という決まりはありません。ECサイトで売り上げを上げるなら、しっかりとしたコンセプトと、コンセプトを決定するまでのリサーチが必要です。

制作会社の考える、業務効率化ツールのおすすめ。個人でも使いやすいサービスなど。

制作会社の考える、業務効率化ツールのおすすめ。個人でも使いやすいサービスなど。

新型コロナウイルス感染拡大の影響で、リモートワークが主流になり、弊社でも週のほとんどは各自宅で作業をしています。

Figmaでデザインのコミット履歴を残せるプラグイン【Thought Recorder】をリリースしました

Figmaでデザインのコミット履歴を残せるプラグイン【Thought Recorder】をリリースしました

Figmaを利用するWebデザイナーの助けになれると嬉しいです。使い方は本記事をご覧ください。

ECの構築方法、おすすめのECサービス。

ECの構築方法、おすすめのECサービス。

ファッションや家電、スーパーの買い物でさえもECサイトを利用することが当たり前になりました。加えて新型コロナウイルスの影響もあり、弊社にも「どんなプラットフォームを利用したら良いか」「どれくらいコストがかかるのか」などECに関するさまざまなご相談を頂きます。

FastAPIのスキーマクラスをOpenAPIから生成する方法

FastAPIのスキーマクラスをOpenAPIから生成する方法

PythonでAPIを構築する要件があり、フレームワークに比較的モダンなFastAPIを採用しました。FastAPIはバックエンドの開発を行えば自動でOepnApi定義を生成する機能が備わっていますが、今回はこれを使わず、事前に用意したOepnApi定義からFastAPIで利用するスキーマクラスを生成する方法を紹介します。

Laravel 日本一解りやすい全文検索のマイグレーション記載方法解説

Laravel 日本一解りやすい全文検索のマイグレーション記載方法解説

Laravel + MySQLで全文検索を実装する

GiFT1号目新卒デザイナーの2021年振り返り

GiFT1号目新卒デザイナーの2021年振り返り

いつの間に、年末ですね。入社してもう、9ヶ月も立っていたようです。2021年の振り返りを記事にしました。

TimesclaeDBのデータ圧縮に関して

TimesclaeDBのデータ圧縮に関して

TimescaleDBはデータベース内の一部のテーブルを時系列データとして扱えるPostgreSQLの拡張です。PostgreSQLの機能拡張なので非常に手軽に導入できます。今回はこのTimesaceDBの圧縮について調べたので備忘録として書き綴りました。

すべての記事

お問い合わせ