prgrm
prgrm

Reputation: 3833

Model combining two tables in Laravel

I have the tables "item", "payment", "join_payment".

The item has an id, the payment has an id. The join_payment has the rows item_id and payment_id.

A payment may contain many items, which would be registered in the join_payment table.

I want to make a log with these items and I am currently doing this in the controller:

$log = Array();

$items = item::where("id",Auth::user()->id)->get();

foreach($items as $item){

$join_payment = join_payment::where("item_id",$item->id)->first();

 if(!array_key_exists($join_payment->payment_id,$log){
  $log[$join_payment->payment_id] = payment::where("id",$join_payment->payment_id)->first();
 }
 $log[$join_payment->payment_id][$item->id] = $item;
}

Is there a way to pull this out with the models?

Upvotes: 2

Views: 55

Answers (2)

Hamelraj
Hamelraj

Reputation: 4826

in your Item model use this

public function payment()
{
   return $this->hasOne('App\Payment','join_payment','payment_id','item_id');
}

then in you loop check

foreach($items as $item){
   dd($item->payment);
}

Upvotes: 1

Jeff
Jeff

Reputation: 25221

I recommend using Eloquent relationships for this. https://laravel.com/docs/5.5/eloquent-relationships#many-to-many. If you call the join table item_payment it will be even easier:

class Item extends Model {
    public function payments(){
        return $this->belongsToMany(Payments::class)
    }
}

class Payment extends Model {
    public function items(){
        return $this->belongsToMany(Item::class)
    }
}

class ItemPayment extends Model {
    public function item(){
        return $this->belongsTo(Item::class)
    }
    public function payment(){
        return $this->belongsTo(Payment::class)
    }
}

Then you can access the data you need in a bunch of ways:

$items = Item::all();
foreach($items as $item){
    $item->payments; //returns all payments belonging to this item
}


$payments = Payment::all();
foreach($payments as $payment){
    $payment->items; //returns all items belonging to this payment
}


$itemPayments = ItemPayment::all();
foreach($itemPayments as $itemPayment){
    $itemPayment->item; //the item for this join
    $itemPayment->payment; //the payment for this join
}

Sorry for changing your class and table names, but these conventions will make your life a ton easier in Laravel

Upvotes: 3

Related Questions