Laravel Eloquent:首先订购多对多查询用户收藏夹


Laravel Eloquent: ordering Many-to-Many query- user favorites first


我的Laravel应用程序返回一个船舶列表供用户管理。我想在其他船只之前返回活动用户"喜爱"的船只。例如:

  • 最佳船舶(*(
  • 我经常管理的船舶(*(
  • 另一艘船
  • 贝塔飞船
  • Cornelia

我在UserShip之间有一个多对多的关系,其中ship->userFavorite返回"喜欢"该船的用户。

我可以想象两种解决方案,但我不确定它们是否可行,如果可行,如何实施。

  1. orderby查询,根据与活动用户相等的收藏夹进行排序

    $ships = Ship::orderby([ship->userfavorite being equal to Auth::User()], 'ASC')
    ->orderby('name', 'ASC')->get();
    
  2. 我目前的解决方案是:我使用wherehas查询首先返回喜爱的船只($favships(,然后使用另一个查询返回所有船只($ships(。对于这个解决方案,我想从第二个查询中删除最喜欢的船只。但是,我如何才能优雅地将这些船只从结果中删除呢?

    $user = Auth::user();
    $favships = Ship::wherehas('userFavorite', function($q) use($user)
    {
        $q->where('id', $user->id);
    })->orderBy('name', 'ASC')->get();
    $ships = Ship::orderBy('name', 'ASC')->get();
    

如果能帮助我加深对这个问题的理解,我们将不胜感激!

您可以使用

$normalShips= $ships->diff($favships);

但我认为您可以将2个查询减少为1个查询:

//Ship.php
public function currentUserFavorite() {
     $this->userFavorite()->where('id', Auth::user()->id);
}

// get all ships
$ships = Ship::with('currentUserFavorite')->orderBy('name', 'ASC')->get();
// finally
$favships = $ships->where('currentUserFavorite.0.id', Auth::user()->id);
$normalShips = $ships->diff($favships);
// or do a loop 
foreach ($ships as $ship) {
    if ($ship->currentUserFavorite->count() > 0) {
      $favships[] = $ship;
    } else {
      $normalShips[] = $ship;
    }
}