ajcastro/eager-load-pivot-relations

Error when paginating after eagerLoading

Opened this issue ยท 9 comments

When chaining a ->paginate() after eager loading the following is thrown:
Call to a member function newCollection() on null in ajcastro/eager-load-pivot-relations/src/EagerLoadPivotBuilder.php on line 78

My scenario is pretty much standard (as the README shows):

users:
  - id
  - name

car_models:
  - id
  - name

colors:
  - id
  - name

user_has_car_model:
  - id
  - user_id
  - car_model_id
  - color_id

Yet, for some reason, we can run:
User::find(1)->cars()->with(['pivot.color'])->get();
but can't do the following
User::find(1)->cars()->with(['pivot.color'])->paginate()

Doing some extra research it turns out on the result to head($pivots) inside EagerLoadPivotBuilder::eagerLoadPivotRelations() is an array with a null value element (array:1 [0 => null]) instead of containing the pivot itself.

@Jesuso Didn't happen to me, I re-created your example and it works on me.
This is what I did:
https://github.com/ajcastro/eager-load-pivot-relations-examples/blob/master/cars/routes/web.php,
using a fresh install of latest laravel(5.8.19) and the latest version of this package (v0.2.1).

@ajcastro I have just got this issue with laravel/framework:7.28.4 and ajcastro/eager-load-pivot-relations:v0.2.2

Did some debugging with the following:

protected function eagerLoadPivotRelations($models, $pivotAccessor)
    {
        dump($pivotAccessor);
        dump($pivots);
        $pivots = Arr::pluck($models, $pivotAccessor);
        dump($pivots);
        dump(head($pivots));
        $pivots = head($pivots)->newCollection($pivots);
        $pivots->load($this->getPivotEagerLoadRelations($pivotAccessor));
    }

and got the following results when calling ->paginate(15)

"pivot"
array:20 [
  0 => App\Models\User ...
  1 => App\Models\User ...
  2 => App\Models\User ...
  3 => App\Models\User ...
  4 => App\Models\User ...
  5 => App\Models\User ...
  6 => App\Models\User ...
  7 => App\Models\User ...
  8 => App\Models\User ...
  9 => App\Models\User ...
  10 => App\Models\User ...
  11 => App\Models\User ...
  12 => App\Models\User ...
  13 => App\Models\User ...
  14 => App\Models\User ...
array:15 [
  0 => null
  1 => null
  2 => null
  3 => null
  4 => null
  5 => null
  6 => null
  7 => null
  8 => null
  9 => null
  10 => null
  11 => null
  12 => null
  13 => null
  14 => null
]
null

and the correct but unpaginated results when just calling ->get()

"pivot"
array:20 [
  0 => App\Models\User ...
  1 => App\Models\User ...
  2 => App\Models\User ...
  3 => App\Models\User ...
  4 => App\Models\User ...
  5 => App\Models\User ...
  6 => App\Models\User ...
  7 => App\Models\User ...
  8 => App\Models\User ...
  9 => App\Models\User ...
  10 => App\Models\User ...
  11 => App\Models\User ...
  12 => App\Models\User ...
  13 => App\Models\User ...
  14 => App\Models\User ...
array:20 [
  0 => App\Models\User ...
  1 => App\Models\User ...
  2 => App\Models\User ...
  3 => App\Models\User ...
  4 => App\Models\User ...
  5 => App\Models\User ...
  6 => App\Models\User ...
  7 => App\Models\User ...
  8 => App\Models\User ...
  9 => App\Models\User ...
  10 => App\Models\User ...
  11 => App\Models\User ...
  12 => App\Models\User ...
  13 => App\Models\User ...
  14 => App\Models\User ...
App\Models\User ...

After a little more investigating I found how to replicate.

Here is your example from above:

User::with(['cars.pivot.color'])->paginate();

I can replicate with the following

User::find(1)->cars()->with(['pivot.color'])->paginate();

Anyone gotten a fix for this? :(

Same issue

Hey @ajcastro ,

First let me thank you for the great package. It saved me a lot of headaches.

Second, I did encounter the same issue mentioned above. This happens whenever you try to load relationships on a relationship function directly and then paginate such as @fennik showed above (but it works if you use ->get() or ->first()).

I don't really know why, but maybe it is related to the way the paginate method works:

    /**
     * Get a paginator for the "select" statement.
     *
     * @param  int|null  $perPage
     * @param  array  $columns
     * @param  string  $pageName
     * @param  int|null  $page
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
    {
        $this->query->addSelect($this->shouldSelect($columns));


        return tap($this->query->paginate($perPage, $columns, $pageName, $page), function ($paginator) {
            $this->hydratePivotRelation($paginator->items());
        });
    }

https://github.com/laravel/framework/blob/7e0e0d0c3dec9f0978d4e616681d86c5749c0b00/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php#L829-L845

The hydratePivotRelation may cause the $pivots = Arr::pluck($models, $pivotAccessor); variable to be null (

$pivots = Arr::pluck($models, $pivotAccessor);
).

Unfortunately, I have not enough knowledge to really understand what is going wrong... But I hope those leads might help :)

Have a nice day

Reopening this so I can take a look later

Thanks a lot ๐Ÿ™๐Ÿพ

@ajcastro did you have a chance to take a look into this?