Tha*_*san 33 php laravel eloquent
我正在使用Laravel并且在Eloquent ORM中遇到一个小问题.我可以使用JOIN简单地使用SQL查询,但我似乎无法使用Eloquent进行操作!
这就是我想要的,我有两个表格.一个是'餐馆',另一个是'Restaurant_Facilities'.
表很简单..和一对一的关系.像有一个restaurant带桌子id,name,slug,等,并叫另一台restaurant_facilities用id,restaurant_id,wifi,parking,等
现在我想做的是..加载所有有wifi = 1或wifi = 0的餐馆..我怎么能用Eloquent做到这一点?我尝试过急切加载,数据透视表,(),集合(),似乎什么都没有用!
对于多对多关系我也有同样的问题cuisines!我有restaurant同桌,cuisine桌子和restaurant_cuisine_connection桌子..
但是如何使用它的ID加载特定菜肴中的所有餐馆?
这有效.
Cuisine::find(6)->restaurants()->get();
但我想从Restaurant :: model而不是菜肴中加载它...因为我有很多条件链接在一起..它用于搜索和过滤/浏览页面.
任何想法或方法?我一直在努力奋斗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');
}
}
Run Code Online (Sandbox Code Playgroud)
PS:这似乎有效..但这不是Eloquent的方式吗?
Restaurant::leftJoin(
'cuisine_restaurant',
'cuisine_restaurant.restaurant_id',
'=', 'restaurants.id'
)
->where('cuisine_id', 16)
->get();
Run Code Online (Sandbox Code Playgroud)
另外,在没有其他查询的情况下,找到具有特定列值的餐馆数量的最佳方法是什么?喜欢..我必须找到停车= 1和wifi = 1的餐厅总数?
请帮忙.
谢谢.
Jef*_*Way 32
如果你必须从餐厅模型加载,我在这里做左连接没有任何问题.我可能会将它抽象为我的餐厅模型上的方法,如下所示:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,从您的路线:
Route::get('/', function()
{
return Restaurant::withWifi()->get();
});
Run Code Online (Sandbox Code Playgroud)
在旅途中 - 没有测试过该代码,但我认为它应该可行.您可以改为使用带有约束的预先加载,但这只会指定设施对象是否为空.它仍将返回所有餐馆,除非您指定where子句.
(PS我会坚持使用单一形式的Facility.请注意如何hasOne('Facilities')正确读取?)
Thr*_*ead 20
在构建新的共享范例时,我偶然发现了这篇文章,同时尝试改进我的REST API方法.您想使用Eager Loading Constraints.假设您有一个api路由,您可以在其中加载共享项目以及它的子集合,例如:
/api/shared/{share_id}/subitem/{subitem_id}
Run Code Online (Sandbox Code Playgroud)
当使用GET请求命中此路由时,您希望加载该特定子项.当然,您可以通过该ID加载该模型,但是如果我们需要验证用户是否可以首先访问该共享项呢?一个答案建议加载反向关系,但这可能会很快导致混乱和混乱的控制器.使用对急切负载的约束是一种更"雄辩"的方法.所以我们这样加载它:
$shared = Shared::where('id', $share_id)
->with([ 'subitems' => function($query) use ($subitem_id) {
$query->where('subitem_id', $subitem_id)
}]);
Run Code Online (Sandbox Code Playgroud)
所以只想要那个有id的子项.现在我们可以通过执行以下操作来检查是否找到了它:
if ($shared->subitems->isEmpty())
Run Code Online (Sandbox Code Playgroud)
由于子项是一个集合(子项目数组),我们返回子项[0]:
return $shared->subitems[0];
Run Code Online (Sandbox Code Playgroud)
Eri*_*ker 14
用于whereHas按任何关系过滤.它不会加入关系,但会通过相关属性过滤当前模型.同时查看本地范围以帮助解决此类情况https://laravel.com/docs/5.3/eloquent#local-scopes
你的例子是:
Restaurant::whereHas('facilities', function($query) {
return $query->where('wifi', true);
})->get();
Restaurant::whereHas('cuisines', function($query) use ($cuisineId) {
return $query->where('id', $cuisineId);
})->get();
Run Code Online (Sandbox Code Playgroud)
使用本地范围实现相同的目标:
class Restaurant extends Eloquent
{
// Relations here
public function scopeHasWifi($query)
{
return $query->whereHas('facilities', function($query) {
return $query->where('wifi', true);
});
}
public function scopeHasCuisine($query, $cuisineId)
{
return $query->whereHas('cuisines', function($query) use ($cuisineId) {
return $query->where('id', $cuisineId);
});
}
}
Run Code Online (Sandbox Code Playgroud)
对于本地作用域,您不希望将它们定义为模型上的静态方法,因为这会创建查询构建器的新实例,并会阻止您链接方法.使用本地作用域将注入并返回查询构建器的当前实例,以便您可以根据需要链接任意数量的作用域:
Restaurant::hasWifi()->hasCuisine(6)->get();
Run Code Online (Sandbox Code Playgroud)
本地作用域使用scope方法名称中的前缀定义,并在方法名称中调用scope,如abover示例中所示.
Yau*_*hyk 10
另一个主演whereHas()功能解决方案:
$with_wifi = function ($query) {
$query->where('wifi', 1);
};
Facilities::whereHas('restaurant', $with_wifi)
Run Code Online (Sandbox Code Playgroud)
干净整洁.