Laravel hasManyの活用法

LaravelのhasManyで明細一括登録 PHP

日々の開発、楽しんでいますか?

開発って、ちょっとした発見があったりして面白いですよね。

今回は、hasMany リレーションの意外な使い方に出会って「そんなことできるの!?」と衝撃を受けたので、共有したいと思います。


hasMany は create にも使える

ズバリ、これです。

実は、Laravelの公式リファレンスにもちゃんと書いてあります。見落としている方も多いかもしれません。

🔗 公式ドキュメント – The create Method


これができると何が嬉しいか?

明細データのように「子テーブルに複数レコードを登録する」ケースで、記述がものすごくスッキリします。


親子データの登録がこんなにスマートに!

$parent->children()->createMany($children);

たったこれだけで、親に紐づく複数の子レコードを一括登録できます。


実例:食事記録アプリを作ってみよう

たとえば、食事記録アプリのように、1回の食事で複数のメニューを登録したい場面を考えてみましょう。
テーブルのリレーションは下図のようなイメージです。


モデルの定義

Meal モデル(親)

class Meal extends Model
{
    use HasFactory;

    protected $fillable = [
        'consumed_at',
        'meal_type',
        'total_calories',
    ];

    public function meal_items()
    {
        return $this->hasMany(MealItem::class, 'meal_id', 'id');
    }
}

MealItem モデル(子)

class MealItem extends Model
{
    use HasFactory;

    protected $fillable = [
        'meal_id',
        'calories',
        'item_name',
    ];

    public function meal()
    {
        return $this->belongsTo(Meal::class, 'meal_id', 'id');
    }
}

🔍 ポイント: MealItembelongsTo() の引数は 'meal_id', 'id' の順で指定するのが正しいです。


データ登録例

// 親データ登録
$meal = Meal::create([
    'consumed_at' => '2025-06-06 07:30:00',
    'meal_type' => 'breakfast',
    'total_calories' => 473,
]);

// 子データ登録
$items = [
    ['item_name' => 'ご飯', 'calories' => 252],
    ['item_name' => '目玉焼き', 'calories' => 135],
    ['item_name' => 'グリーンサラダ', 'calories' => 25],
    ['item_name' => 'わかめと豆腐の味噌汁', 'calories' => 61],
];

$meal->meal_items()->createMany($items);

このように、シンプルなコードで「親 + 複数の子」をきれいに登録できます。


注意点:create() と createMany() の違い

  • ✅ 単一レコード → create([...])
  • ❌ 複数レコード → create([[...] , [...]]) はエラーになる
  • ✅ 複数レコード → createMany([[...], [...], ...])

複数登録のときは、createMany() を使う点に注意です。


まとめ

複雑な前処理やループを書かずに、Eloquentの機能だけでスッキリ記述できるのは大きなメリットです。

このように、データ加工と登録処理を分離して書けば、コードの可読性と保守性が大きく向上します。

Laravelが用意してくれている便利な機能は、積極的に活用していきましょう!