2

How to define relationship in Laravel using composite keys?

I have 2 tables which have 2 primary keys, order [id_order, id_trip] and detail order [id_trip, id_seat].

I tried to get $order->detail_order->id_seat in index.blade.php, but the error is Array to string conversion (View: D:\xampp\htdocs\travel\resources\views\order\index.blade.php)

I think I have a mistake in defining relationship in model. Here's my code :

Order.php

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Traits\CompositeKeyTrait;

class Order extends Model{

    use CompositeKeyTrait;
    protected $table = "order";
    protected $fillable = [
        'id_order',
        'id_trip', 
        'id_users_customer', 
        'date_order',
        'id_users_operator'
    ];

    protected $primaryKey = ['id_order', 'id_trip'];

    public function detail_order(){   
        return $this->hasMany(Detail_Order::class);   
    }
}

Detail_Order.php

<?php

namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Traits\CompositeKeyTrait;

class Detail_Order extends Model{
    use CompositeKeyTrait;

    protected $table = "detail_order";
    protected $fillable = [
        'id_trip',  
        'id_seat',
        'id_users_feeder', 
        'id_order',
        etc
    ];

    protected $primaryKey = ['id_trip', 'id_seat'];

    public function order(){
        return $this->belongsTo(Order::class, 'id_order', 'id_trip');
    }
}

index.blade.php

     @foreach($order as $o)
        <tr>
            <td>{{ $o->detail_order->id_seat }}</td>
        </tr>
     @endforeach

Does anyone have any idea? Thanks.

Swatantra Kumar
  • 1,324
  • 5
  • 24
  • 32
beginner
  • 33
  • 1
  • 11

2 Answers2

0

Laravel does not support Composite Primary Key. You hit "Array to string conversion" error becouse Laravel try to cast array to string.

protected $primaryKey = ['id_order', 'id_trip'];
baceto90
  • 33
  • 4
  • Thanks. I use trait for composite key (https://daengweb.id/diary-error/composite-key-laravel), and it works in other relationship. Example: $order->user->name. The table user has 1 primary key. But when I tried to get relationship between order table and detail_order table, i got error. Perhaps it's because order and detail_order table they both have 2 primary keys. – beginner Apr 13 '20 at 00:53
0

You can't. Eloquent doesn't support composite primary keys. But you can do using an open-source package called LaravelTreats.

Hope this helps you

Ref: https://stackoverflow.com/a/36995763/10765839

Kaushik Thakkar
  • 344
  • 3
  • 10
  • Thanks. I use trait for composite key (daengweb.id/diary-error/composite-key-laravel), and it works in other relationship. Example: $order->user->name. The table user has 1 primary key. But when I tried to get relationship between order table and detail_order table, i got error. Perhaps it's because order and detail_order table they both have 2 primary keys. – beginner Apr 13 '20 at 00:42
  • You're welcome. Does it required to use Composite primary key? Anyway you can use unique with not null to get the same functionality of primary key. Just curious to understand that. – Kaushik Thakkar Apr 13 '20 at 00:46
  • I am afraid that i have to use composite primary key. Because id_order and id_trip column is needed in detail_order table. – beginner Apr 13 '20 at 00:50
  • In `detail_order` table, you can have a foreign key which will have data from the `order` ( your reference table for order) and `trip` table ( your reference table for trip). Both tables have one primary key, Right? – Kaushik Thakkar Apr 13 '20 at 00:54
  • Yes, the 'trip' table has one primary key. 'trip' table hasMany 'order' table. And 'order' table hasMany 'detai_order'. So, i get data just from order table (because in order, it has data from Trip table) – beginner Apr 13 '20 at 01:05
  • Getting confused. Can you tell me how any **trip** can have multiple records in **order table** and **order table** can have multiple records in **detail_order** table? – Kaushik Thakkar Apr 13 '20 at 01:16
  • For example : Trip (id_trip, from, to) = {'T1', 'London', 'Sheffield'}, {T2, 'Aberdeen', 'Edinburgh'}. Order (id_order, id_trip, date_order) = {'O1', 'T1', currentdatetime}, {'O2', 'T2', currentdatetime}. Detail_Order (id_trip, id_order, id_seat, name) = {'T1', 'O1', 1, Sarah}, {'T1, 'O1', 2, 'Alex'}, {'T2', 'O2', 1, 'Brian'}. Trip PK = id_trip. Order PK = id_order, id_trip. Detail Order PK = id_trip, id_seat (Because one trip can only have 7 seats). Explanation : Sarah wanna go to Sheffield, she's in London now. So she orders 2 seats for her and Alex. Sorry if this case confuses you – beginner Apr 13 '20 at 01:49
  • Okay, got your point. - As I can I see there is one trip linked with one order so you can use - one of these: `belongsTo, hasOne, hasOneThrough`. -In `order_details` table, `trip_id` and `order_id` must exist into trip, and order table. So you can use the foreign key, no need to use the composite primary _[CP]_ key. If you us _CP_, there is a possibility that you can have a value that doesn't belong to the trip or order table for trip_id or order_id. Using foreign keys, you can stop that. – Kaushik Thakkar Apr 13 '20 at 02:05
  • Thanks for your advice, I will try this – beginner Apr 13 '20 at 02:27
  • My pleasure. Let me know If you find any issue while trying that. – Kaushik Thakkar Apr 13 '20 at 02:37
  • As far as I know, none of the available packages to solve the composite keys' limitation offer support for many-to-many relationships. Right? – Javerleo Dec 17 '21 at 17:46