Laravel 6で、親・子・孫のモデルを取得する

Laravel Laravel

Laravelの書籍では、「親・子」のリレーションに関する記載はよく見られますが、「親・子・孫」のリレーションに関しては見たことがありません。

下記のような構造のモデルがあったとします。

会員(users)が注文(orders)して、複数の注文詳細(order_details)があります。

usersとordersとorder_detailsの関係は、

  • users → orders hasMany
  • orders → order_details hasMany

となっていて、「親・子・孫」の関係になっています。

各モデルには下記のようにリレーションを書きました。

/**
 * Orderとのリレーション
 */
public function order()
{
    return $this->hasMany('App\Order');
}
/**
 * Userとのリレーション
 */
public function user()
{
    return $this->belongsTo('App\User');
}

/**
 * OrderDetailとのリレーション
 */
public function orderDetail()
{
   return $this->hasMany('App\OrderDetail');
}
/**
 * Orderとのリレーション
 */
public function order()
{
    return $this->belongsTo('App\Order');
}

コントローラで下記のように記述しましたが、エラーになりました。

public function index()
{
    $items = Auth::user()->order()->orderDetail;

}

Laravalのドキュメントを眺めたところ、「hasMenyThrough」というリレーションを使いなさい、と書いてありました。

6.x Eloquent:リレーション Laravel

Userモデルに下記を追記します。

/**
 * OrderDetailとのリレーション
 */
public function orderDetail()
{
    return $this->hasManyThrough('App\OrderDetail', 'App\Order');
}

コントローラで下記のように記述すると、データが取得できました。

public function index()
{
    $items = Auth::user()->orderDetail;

}

ただ、この方法だと「orderDetail」モデルの情報しか取得できないので、下記のように書いてみました。

public function index()
{
    $items = Auth::user()->with('order')->with('orderDetail')->get();

}

このようにデータが取得できました。

しかし、この方法だとOrderとOrderDetail(子と孫)がオブジェクトの中で並列の関係になってしまっています。

あれこれ試してみましたがうまく行かず、結局この方法が一番いいのかも?と思いました。

public function index()
{
    $items = Order::with('orderDetail')
        ->where('orders.user_id', '=', Auth::user()->id)
        ->get();

}

ちゃんとOrderとOrderDetailが「子と孫」の関係になっています。

この記事を書いた人

余分なこだわりは捨てる。それがぼくのスタイル。

PHPでWebアプリを作り、小さな花の写真を撮ってよろこんでいる人。元Webエンジニア。プログラミング講師。余分なこだわりを捨てて生きやすくなりたいと思いつつも、なかなかこだわりを捨てきれない頑固者。まろと呼んでください。

さかのうえの まろをフォローする
Laravel
シェアする