【问题标题】:Laravel Eloquent split large query in to chunk and reuse itLaravel Eloquent 将大型查询拆分为块并重用它
【发布时间】:2018-10-20 18:50:05
【问题描述】:

我有一个非常大的查询格式,如下所示。我想拆分它并需要重新用于许多其他 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);
                }
            }
        }
    }
?>

有什么方法可以让我从刀片或以任何其他方式包含此代码。

注意:我需要重复使用很多这样的东西。

【问题讨论】:

  • 是的,制作一个刀片文件并在刀片中的任何位置使用它,在 @section("example") 中添加您的代码,在您想要使用它的每个位置将 @yield("example") 放入
  • @Babak 第一个查询在控制器内
  • 为此在助手中创建一个函数,并在你想要以太控制器或刀片的任何地方调用它
  • 我正在使用来自request 的许多变量,所以我认为助手不会提供帮助
  • 好吧,您可以在代码顶部添加这样的代码$request = request();

标签: php laravel reusability code-reuse laravel-5.6


【解决方案1】:

您可以做的第一件事是将其中一些功能分解为范围: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 而无需重新编写太多代码,而对于其他范围,您可以提取更多代码。

你也可以创建一个 Transformer 类来改变它:

    $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

【讨论】:

    猜你喜欢
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 2018-12-21
    • 2016-09-30
    • 2020-07-18
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    相关资源
    最近更新 更多