0

I have 2 tables: t1: hotels t2: people

There are 5 hotels and in every hotel a different number of people. I'd like to get hotel name and people's names assigned to that hotel. With the query I have it duplicated the hotel name as many times as there are people in it.

$hotels=DB::table('hotels')
->select('hotels.*','people.name')
->leftjoin('people','people.hotel_id','=','hotel.id')
->get();

return view('hotels', ['hotels' => $hotels]);

And in my view I have

@foreach($hotels as $h)
$h->hotel_name
@endforeach

hotel_name now shows up 4 times which is the same number of people assigned to the hotel_id. I've tried using group_concat but with that I could only get the names of the people.

Is there a group by or some other method which could help me to get to my goal?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Studio DnB
  • 19
  • 9

5 Answers5

3

In your HotelModel

public function peoples()
{
    return $this->hasMany('App\People','hotel_id');
}

In your Controller
(use ->with('peoples') to solve the n+1 problem.

$hotels = Hotel::with('peoples')->get();    
return view('hotels', ['hotels' => $hotels]);

In your View

@foreach($hotels as $h)
    $h->hotel_name

    @foreach($h->peoples as $people)
        $people->name
    @endforeach

@endforeach
ndberg
  • 3,391
  • 1
  • 21
  • 36
Faraz Irfan
  • 1,306
  • 3
  • 10
  • 17
1

Actually you can achieve this using group_concat and group_by like so :

select hotels.* ,group_concat(people.name) as people_names
from hotels 
  left join people on hotels.id = people.hotel_id 
group by hotel_name;

using the query builder :

$hotels = DB::table('hotels')
   ->select('hotels.*', DB::raw('group_concat(people.name) as people_names'))
   ->leftjoin('people','people.hotel_id','=','hotels.id')
   ->groupBy('hotel_name')
   ->get();
Amr Aly
  • 3,871
  • 2
  • 16
  • 33
0

Add to your Hotel class

public function peoples()
{
    return $this->hasMany(People::class);
}

In your view:

@foreach ($hotel->people as $people)
    {{ $people->name }}
@endforeach
J. Doe
  • 1,682
  • 11
  • 22
0

Try to use Collection's groupBy function:

$hotels=DB::table('hotels')
->select('hotels.*','people.name')
->leftjoin('people','people.hotel_id','=','hotel.id')
->get();
$grouped = $hotels->groupBy('hotel_name');

return view('hotels', ['hotels' => $grouped]);

And then, print it like this:

@foreach($hotels as $key => $h)
    Hotel name: {{ $key }}
    @foreach ($h as $p)
        Person name: {{ $p }}
    @endforeach 
@endforeach
Laerte
  • 7,013
  • 3
  • 32
  • 50
  • Hotel name: {{ $key }} displays nothing. Also in this case how can I get hotel_name, hotel_location and so on? – Studio DnB Apr 23 '18 at 15:19
  • Using this, you will need to select them. Try to `dd($grouped);` to see how the information is organized. It will clarify it. – Laerte Apr 23 '18 at 17:56
0

Make a Hotel model and define the relationship:

public function people()
{
    return $this->hasMany(People::class);
} 

I'm your controller:

$hotels = Hotel::all():
return view('hotels')->with('hotels', $hotels);

In your view:

@foreach($hotels as $hotel)

    {{ $hotel->name }}

    @foreach($hotel->people as $person)
        {{ $person->name }}
    @endforeach

@endforeach
parker_codes
  • 3,267
  • 1
  • 19
  • 27
  • I'm recommend you to read about [n-query problem](https://laravel.com/docs/5.6/eloquent-relationships#eager-loading). Your example could propagate a bad habit. – Wojciech Mleczek Apr 26 '18 at 10:17