Search code examples
mysqlsqllaravellaravel-5.3

Get highest & lowest data based on a whereHas query


Based on an apartment finder all types which has apartments, based on the form search are being shown/returned. This is being done using a whereHas query.

So for example:

A user has different choices; a garden/balcony, price range, floor etc.

The query is being run based on these choices, and if there are apartments which meet the search requirements the parent of these apartments (type) are being returned.

Ultimately I want to display the living surface range (lowest-highest) of a type, but the living surface is different for each apartment.

What would be the most effective way to get the highest and lowest apartment.living_surface being returned by the whereHas.

$types = Type::where('type', '=', 'studio')->whereHas('apartments', function ($query) use ($request) {
    if ($request->view == 'garden') {
        $query->where('view', '=', $request->view);
    } elseif ($request->view == 'balcony') {
        $query->where('view', '=', $request->view);
    } elseif ($request->view == 'other') {
        $query->where('view', '=', $request->view);
    }

    if ($request->floor == 'upper') {
        $query->where('floor', '<', '5');
    } elseif ($request->floor == 'lower') {
        $query->where('floor', '>', '4');
    }

    if ($request->sun == 'morning') {
        $query->where('sun', '=', 'morning');
    } elseif ($request->sun == 'evening') {
        $query->where('sun', '=', 'evening');
    }

    if ($request->price == '1') {
        $query->where('price', '<', '900');
    } elseif ($request->price == '2') {
        $query->where('price', '<', '999');
    } elseif ($request->price == '3') {
        $query->where('price', '>', '999');
    }
})->with('apartments')->get();

One solution would be (I think) is to pluck all ids of the apartments and run another query based on the ids, but this wouldn't really be as optimized as possible due to running multiple queries for something (I hope) to be done within one query.


Solution

  • This can be done by the Collection Methods - Laravel Docs

    It is possible to run methods over the queried collection - in this case $types

    foreach ($types as $type) {
        $type->lowest_living_area = $type->apartments>sortBy('living_area')->first()->living_area);
        $type->highest_living_area = $type->apartments->sortBy('living_area')->last()->living_area);
    }