Laravel Eloquent 将大型查询拆分成块并重复使用
Laravel Eloquent split large query in to chunk and reuse it
我真的有一个非常大的查询结构,如下所示。我想拆分这个并且需要 re-use 用于许多其他 ajax 调用的
$buildquery=Hotel::has('room');
$buildquery->whereHas('room', function($query) use ($request) {
// If amenities is there add it to query
if($request->filled('amenities')){
$amenities = $request->amenities;
$count = count($amenities);
$query->withCount(['amenities' => function($query) use ($amenities, $count){
$query->whereIn('amenities_id', $amenities);
}])
->having('amenities_count', $count);
}
/* filter based on guest */
if($request->filled('guestsCount')){
$memberCount = $request->guestsCount + $request->childCount;
$query->Where('capacity', '>=', $memberCount);
}else{
$query->Where('capacity', '>=', 1);
}
});
$buildquery->with(['room' => function ($query) use ($request) {
// If amenities is there add it to query
if($request->filled('amenities')){
$amenities = $request->amenities;
$count = count($amenities);
$query->withCount(['amenities' => function($query) use ($amenities, $count){
$query->whereIn('amenities_id', $amenities);
}])
->having('amenities_count', $count);
}
/* filter based on guest */
if($request->filled('guestsCount')){
$memberCount = $request->guestsCount + $request->childCount;
$query->Where('capacity', '>=', $memberCount);
}else{
$query->Where('capacity', '>=', 1);
}
$query->with('roomtype')->with('floorroomcount')->with('image')->with('amenities');
$query->OrderBy('price');
$query->Where('astatus', 1)->Where('status', 0);
}]);
/* client must be active */
$buildquery->whereHas('client', function($query) {
$query->Where('status', 1);
});
/* search based on rating */
if ($request->filled('rating')) {
if($request->rating > 0){
$rating = $request->rating;
$buildquery->where('star', $rating);
}
}
/* search based on hotel */
if ($request->filled('location_id')) {
$buildquery->Where('city', $request->location_id);
}
@include('roomlist.area');
$buildquery->Where('astatus', 1)->where('status', 0); //actually its hotel
$hotels = $buildquery->simplePaginate(20);
$hotels = $this->addRates($hotels, $request->checkin_date, $request->checkout_date);
$hotels = $this->addAvailableCount($hotels, $request->checkin_date, $request->checkout_date);
$hotels = $hotels->transform(function (Hotel $hotel){
$hotel->setRelation('room', $hotel->room->sortBy('price')->flatten());
return $hotel;
});
return view('roomlist.loadmore', compact('hotels'));
请查看 roomlist/area.blade.php
文件中的这一行 @include('roomlist.area');
我有以下代码
<?php
if($request->filled('type')){
if($request->type == "Area"){
//get the area first
$hotel = Hotel::select('area')->where('city', $request->location_id)->first();
if(isset($hotel)){
if($hotel->area != null){
$buildquery->where('area', $hotel->area);
}
}
}
}
?>
有什么方法可以从 blade 或任何其他方式包含此代码。
注意:我需要re-use很多这样的东西。
您可以做的第一件事是将其中一些功能分解为范围:https://laravel.com/docs/5.6/eloquent#query-scopes
例如,您可以更改为:
/* search based on hotel */
if ($request->filled('location_id')) {
$buildquery->Where('city', $request->location_id);
}
进入这个:
if ($request->filled('location_id')) {
$buildquery->inCity($request->location_id);
}
或者这个:
/* client must be active */
$buildquery->whereHas('client', function($query) {
$query->Where('status', 1);
});
进入这个:
$buildquery->withActiveClient();
这是一个小改动,但它允许您在其他地方使用 inCity
而无需重写太多,对于其他范围,您可以提取更多代码。
你也可以制作一个变形金刚 class 来改变这个:
$hotels = $hotels->transform(function (Hotel $hotel){
$hotel->setRelation('room', $hotel->room->sortBy('price')->flatten());
return $hotel;
});
为此:
$hotels = (new HotelRoomTransformer())->transform($hotels);
这种类型的提取代码可以使该文件更具可读性,这样一来,如果您需要重用它的一部分,您可以将它们放在单独的、可重用的文件中。
最后,如果您想从控制器中完全删除 Eloquent,则可以将此类功能全部提取到存储库中。这是关于存储库模式的简短指南:https://medium.com/@connorleech/use-the-repository-design-pattern-in-a-laravel-application-13f0b46a3dce
我真的有一个非常大的查询结构,如下所示。我想拆分这个并且需要 re-use 用于许多其他 ajax 调用的
$buildquery=Hotel::has('room');
$buildquery->whereHas('room', function($query) use ($request) {
// If amenities is there add it to query
if($request->filled('amenities')){
$amenities = $request->amenities;
$count = count($amenities);
$query->withCount(['amenities' => function($query) use ($amenities, $count){
$query->whereIn('amenities_id', $amenities);
}])
->having('amenities_count', $count);
}
/* filter based on guest */
if($request->filled('guestsCount')){
$memberCount = $request->guestsCount + $request->childCount;
$query->Where('capacity', '>=', $memberCount);
}else{
$query->Where('capacity', '>=', 1);
}
});
$buildquery->with(['room' => function ($query) use ($request) {
// If amenities is there add it to query
if($request->filled('amenities')){
$amenities = $request->amenities;
$count = count($amenities);
$query->withCount(['amenities' => function($query) use ($amenities, $count){
$query->whereIn('amenities_id', $amenities);
}])
->having('amenities_count', $count);
}
/* filter based on guest */
if($request->filled('guestsCount')){
$memberCount = $request->guestsCount + $request->childCount;
$query->Where('capacity', '>=', $memberCount);
}else{
$query->Where('capacity', '>=', 1);
}
$query->with('roomtype')->with('floorroomcount')->with('image')->with('amenities');
$query->OrderBy('price');
$query->Where('astatus', 1)->Where('status', 0);
}]);
/* client must be active */
$buildquery->whereHas('client', function($query) {
$query->Where('status', 1);
});
/* search based on rating */
if ($request->filled('rating')) {
if($request->rating > 0){
$rating = $request->rating;
$buildquery->where('star', $rating);
}
}
/* search based on hotel */
if ($request->filled('location_id')) {
$buildquery->Where('city', $request->location_id);
}
@include('roomlist.area');
$buildquery->Where('astatus', 1)->where('status', 0); //actually its hotel
$hotels = $buildquery->simplePaginate(20);
$hotels = $this->addRates($hotels, $request->checkin_date, $request->checkout_date);
$hotels = $this->addAvailableCount($hotels, $request->checkin_date, $request->checkout_date);
$hotels = $hotels->transform(function (Hotel $hotel){
$hotel->setRelation('room', $hotel->room->sortBy('price')->flatten());
return $hotel;
});
return view('roomlist.loadmore', compact('hotels'));
请查看 roomlist/area.blade.php
文件中的这一行 @include('roomlist.area');
我有以下代码
<?php
if($request->filled('type')){
if($request->type == "Area"){
//get the area first
$hotel = Hotel::select('area')->where('city', $request->location_id)->first();
if(isset($hotel)){
if($hotel->area != null){
$buildquery->where('area', $hotel->area);
}
}
}
}
?>
有什么方法可以从 blade 或任何其他方式包含此代码。
注意:我需要re-use很多这样的东西。
您可以做的第一件事是将其中一些功能分解为范围:https://laravel.com/docs/5.6/eloquent#query-scopes
例如,您可以更改为:
/* search based on hotel */
if ($request->filled('location_id')) {
$buildquery->Where('city', $request->location_id);
}
进入这个:
if ($request->filled('location_id')) {
$buildquery->inCity($request->location_id);
}
或者这个:
/* client must be active */
$buildquery->whereHas('client', function($query) {
$query->Where('status', 1);
});
进入这个:
$buildquery->withActiveClient();
这是一个小改动,但它允许您在其他地方使用 inCity
而无需重写太多,对于其他范围,您可以提取更多代码。
你也可以制作一个变形金刚 class 来改变这个:
$hotels = $hotels->transform(function (Hotel $hotel){
$hotel->setRelation('room', $hotel->room->sortBy('price')->flatten());
return $hotel;
});
为此:
$hotels = (new HotelRoomTransformer())->transform($hotels);
这种类型的提取代码可以使该文件更具可读性,这样一来,如果您需要重用它的一部分,您可以将它们放在单独的、可重用的文件中。
最后,如果您想从控制器中完全删除 Eloquent,则可以将此类功能全部提取到存储库中。这是关于存储库模式的简短指南:https://medium.com/@connorleech/use-the-repository-design-pattern-in-a-laravel-application-13f0b46a3dce