compoships icon indicating copy to clipboard operation
compoships copied to clipboard

Laravel upgrade - Cannot access distant relations anymore

Open sptdigital opened this issue 1 year ago • 4 comments

Hi there,

First of all thank you for having maintained the library for so long it has been great so far. Today I was trying to upgrade our Laravel to version 8 (from 6...) but the app breaks partially where trying to eager load distant relations on models implementing compoships.

I am trying to understand what's going on or what I am doing wrong.

Current versions Laravel: 8.83 Compoships: 2.0.5 (tried 2.0.3 and also the latest too)

all relations where using compoship are belongsTo or hasMany

I have these 3 models with relations defined as below, all tables having 50K+ records

class A extends Model
{   
    public function b()
    {
        return $this->hasMany('B', 'B-k1', 'A-k1');
    }
}
class B extends Model
{
    use \Awobaz\Compoships\Compoships;
    
    public function a()
    {
        return $this->belongsTo('A', 'A-k1', 'B-k1');
    }

    public function c()
    {
        return $this->hasMany('C', ['C-k1', 'C-k2'], ['B-k1', 'B-k2']);
    }
}
class C extends Model
{
    use \Awobaz\Compoships\Compoships;
    
    public function b()
    {
        return $this->belongsTo('B', ['B-k1', 'B-k2'], ['C-k1', 'C-k2']);
    }
}

The response I used to get in L6 when querying A and it's children relations A.B.C

A
    B
        C
        C
        C
        C
    B
        C
        C

The response I am getting now

A
    B
    B
    B
    B
    ...
    ...
    50K B's
    ...
    death loop
    dies with 500

I have tested all relations individually on a direct parent > child basis and they all work, so requesting A > B or B > C works but when trying to nest A B C fails with the query trying to get all the B's fron the Database regardless of the parent relation with A

Any hint would be appreciated

Thanks

sptdigital avatar Aug 31 '23 15:08 sptdigital

Can you please share a code example of querying A and it's children relations A.B.C? I also suggest to check the query log (via Laravel Debugbar or ...) to get an idea of the SQL queries.

topclaudy avatar Aug 31 '23 20:08 topclaudy

Sure @topclaudy

The below is the relation from what I referred as Model A (\App\Contract), it hasMany \App\PickupPoint (model B) joining on the tender_ref_no column. I am trying to eager load all PickupTime (model C) for each PickupPoint.

When I remove the ->with('pickupTimes') I am getting the relevant PickupPoint(s) for the Contract, (2 or them) as soon as I am trying to eagerload PickupTimes it fetches all PickupPoint for all Contracts... resulting in a massive query

/**
     * @Relation
     */
    public function pickupPoints()
    {
        return $this->hasMany(\App\PickupPoint::class, 'tender_ref_no', 'tender_ref_no')->with('pickupTimes');
    }

The queries running

select * from `contracts`.`contracts` where `tender_ref_no` = ? and `stat_ind` not in (?, ?) and `contracts`.`contracts`.`deleted_at` is null limit 1

Bindings:
array:3 [▼
  0 => "G1234"
  1 => 50
  2 => 99
]
"select * from `schools`.`pickup_points` where `schools`.`pickup_points`.`tender_ref_no` in (0)"

Bindings:  somehow ending up with (0), should bind to G1234,
[]

then basically thousands of lines like this with huge bindings array with all Contract(s) and PickupPoint(s) IDs

select * from `schools`.`pickup_times` where ((`schools`.`pickup_times`.`tender_ref_no` = ? and `schools`.`pickup_times`.`pickup_pt_no` = ?) or (`schools`.`pickup_times`.`tender_ref_no` = ? and `schools`.`pickup_times`.`pickup_pt_no` = ?) or (`schools`.`pickup_times`.`tender_ref_no` = ? and `schools`.`pickup_times`.`pickup_pt_no` = ?) or (`schools`.`pickup_times`.`tender_ref_no` = ? and `schools`.`pickup_times`.`pickup_pt_no` = ?) or .........

Thanks again

sptdigital avatar Sep 01 '23 12:09 sptdigital

@sptdigital Thanks for the follow-up. I'm not sure whether it's a problem with Compoships or a recent change in Eloquent relationships behavior. I'd suggest to remove the ->with('pickupTimes') from the definition of the relationship and move it to the part where you retrieve the data.

topclaudy avatar Sep 01 '23 16:09 topclaudy

You shouldn't use with inside a relation, just try->with('pickupPoints.pickupTimes') on main query, it has nested relations

parallels999 avatar Oct 04 '23 19:10 parallels999