phplaravellaravel-7table-relationships

How to create a relation between 3 tables in laravel 7?


I have three tables in a DB. The first one is "bookings" with some columns: id, customer_id, etc. The second one is "customer" with id, name, email etc.

And the third one is "customer_meta" with id, object_id (which is the reference to the id column from the "customer" table), meta_key and meta_value. It contains additional data about the customer like DOB, passport number, gender etc. Each row from this table is a different entry for a particular customer, like so:

id object_id meta_key meta_value
1 1 cf_x4rMBfn3 10/11/1989
2 1 cf_x4rMBfb5 1234567
3 1 cf_x4rMB735 M

I've created a One To Many relationship between the bookings and customer table. This is the code for my index function in my controller.

public function index()
{
    
    $bookings = Booking::with('customer')->get();
   
    return view('bookings', [
        'bookings' => $bookings,
    ]);

}

All is working well. I can display the data in my blade file like so:

<tbody>
    
        @foreach ( $bookings as $booking )
            <tr>
                <td>{{ $booking->id }}</td>
                <td>{{ $booking->start_date }}</td>
                <td>{{ $booking->customer->first_name }}</td>
                <td>{{ $booking->customer->last_name }}</td>
            </tr>
        @endforeach

    </tbody>

And now I want to access the data from "customer_meta". I can't seem to figure out the type of relationship between the "bookings" table and the "customer_meta" table. I want to display all the rows for a particular customer through the "booking" that contains the customer_id.


Solution

  • If you set up the relationship between customer and customer_meta you should be able to access it like

    class Customer extends Model
    {
        public function customerMeta()
        {
            return $this->hasMany(App\Models\CustomerMeta::class, 'object_id', 'id');
    
        }
    }
    
    
    $bookings = Booking::with('customer', 'customer.customerMeta')->get();     
    ...
            
    {{ $booking->customer->customerMeta->meta_key }}
    

    You could use 'has one through' or 'has many through' relationship if you want to access customer_meta directly from the booking record see https://laravel.com/docs/7.x/eloquent-relationships#has-one-through.

    This way you can access customer_meta directly from the booking record

    class Booking extends Model 
    {
        public function customerMeta()
        {
          return $this->hasOneThrough(App\Models\CustomerMeta::class, App\Models\Customer::class);
        }
    }