Laravel,如何使用关系列的 where 条件?

2022-08-30 13:06:34

我正在使用Laravel,并且在Eloquent ORM上有一个小问题。我可以使用JOIN简单地使用SQL查询来工作,但我似乎无法让它与Eloquent一起工作!

这就是我想要的,我有两个标签。一个是“餐馆”,另一个是“Restaurant_Facilities”。

表格很简单。和一对一关系。就像有一个表有 , , , 等 和 另一个表叫 , , , , , 等restaurantidnameslugrestaurant_facilitiesidrestaurant_idwifiparking

现在我想做的是..加载所有有wifi = 1或wifi = 0的餐厅。我怎么能用Eloquent做到这一点?我已经尝试了急切加载,数据透视表,with(),collections()似乎没有任何效果!

我对多对多关系有同样的问题!我有同一张桌子,一张桌子和一张桌子。cuisinesrestaurantcuisinerestaurant_cuisine_connection

但是我如何使用其ID加载特定美食中的所有餐厅?

这有效。

Cuisine::find(6)->restaurants()->get();

但我想从餐厅加载这个:模型不是从美食。因为我有很多条件链接在一起..它用于搜索和过滤/浏览页面。

任何想法或方法?我已经为此挣扎了3天,仍然没有答案。

示例模型 :

class Restaurant extends Eloquent {

    protected $table = 'restaurants';

    public function facilities() {
        return $this->hasOne('Facilities'); 
    }
}

class Facilities extends Eloquent {

    protected $table = 'restaurants_facilities';

    public function restaurant() {
        return $this->belongsTo('Restaurant');
    }

}

PS :这似乎正在工作。但这不是雄辩的方式对吧?

Restaurant::leftJoin(
                'cuisine_restaurant', 
                'cuisine_restaurant.restaurant_id', 
                '=', 'restaurants.id'
             )
             ->where('cuisine_id', 16)
               ->get();

另外,在没有其他查询的情况下查找具有特定列值的餐馆计数的最佳方法是什么?喜欢。。我必须找到有停车场=1和wifi=1的餐厅总数?

请对此提供帮助。

谢谢。


答案 1

如果您必须从餐厅模型中加载,我不认为在此处执行左连接有什么问题。我可能会把它抽象为我的餐厅模型上的一个方法,就像这样:

class Restaurant extends Eloquent {
    protected $table = 'restaurants'; // will be default in latest L4 beta

    public function facility()
    {
      return $this->hasOne('Facility');
    }

    // Or, better, make public, and inject instance to controller.
    public static function withWifi()
    {
      return static::leftJoin(
        'restaurant_facilities',
        'restaurants.id', '=', 'restaurant_facilities.restaurant_id'
      )->where('wifi', '=', 1);
    }
}

然后,从您的路线:

Route::get('/', function()
{
  return Restaurant::withWifi()->get();
});

在旅途中 - 还没有测试过该代码,但我认为它应该有效。您可以改为使用带有约束的预先加载,但这只会指定设施对象是否为 null。它仍将返回所有餐馆,除非您指定 where 子句。

(附言我会坚持使用单一形式的设施。注意如何不能正确阅读?hasOne('Facilities')


答案 2

在构建新的共享范式时,我偶然发现了这篇文章,同时试图改进我的REST API方法。您希望使用预先加载约束。假设您有一个 api 路由,您可以在其中加载共享项目,它是子项的集合,如下所示:

/api/shared/{share_id}/subitem/{subitem_id}

使用 GET 请求命中此路由时,需要加载该特定子项。当然,您可以只通过该 ID 加载该模型,但是如果我们需要首先验证用户是否有权访问该共享项目,该怎么办?一个答案建议加载反转关系,但这可能会导致控制器很快变得混乱和混乱。对预先加载使用约束是一种更“雄辩”的方法。所以我们会像这样加载它:

$shared = Shared::where('id', $share_id)
  ->with([ 'subitems' => function($query) use ($subitem_id) {
    $query->where('subitem_id', $subitem_id)
  }]);

因此,哪里只需要具有该ID的子项。现在,我们可以通过执行以下操作来检查它是否被找到:

if ($shared->subitems->isEmpty())

由于子项是一个集合(子项数组),因此我们返回子项[0],如下所示:

return $shared->subitems[0];

推荐