topclaudy / compoships

Multi-columns relationships for Laravel's Eloquent ORM
MIT License
1.1k stars 130 forks source link

Laravel upgrade - Cannot access distant relations anymore #161

Open sptdigital opened 1 year ago

sptdigital commented 1 year ago

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

topclaudy commented 1 year ago

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.

sptdigital commented 1 year ago

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

topclaudy commented 1 year ago

@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.

parallels999 commented 11 months ago

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