datarecall's avatar

Pagination Problem + Eloquent Help

Help With Pagination

I have a model called "supplier" and this model has many "products"

Each product has a rating with is attached by a pivot table product_id / diary_id

I am currently using this to get the $supplier ratings

public function getRatingsAttribute()
    {
        return $this->products()->with('ratings.user')->get()->pluck('ratings')->sortByDesc('created_at');
    }

which returns this

Illuminate\Support\Collection {#4351
  #items: array:1 [
    0 => Illuminate\Database\Eloquent\Collection {#4359
      #items: array:1 [
        0 => App\Diary {#4364
          +fillable: array:5 [
            0 => "user_id"
            1 => "name"
            2 => "type"
            3 => "grow_medium"
            4 => "published_at"
          ]
          #with: array:2 [
            0 => "media"
            1 => "user"
          ]
          #appends: array:3 [
            0 => "thumbCoverUrl"
            1 => "route"
            2 => "isHarvested"
          ]
          #casts: array:2 [
            "user_id" => "integer"
            "published_at" => "datetime"
          ]
          #connection: "sqlite"
          #table: "diaries"
          #primaryKey: "id"
          #keyType: "int"
          +incrementing: true
          #withCount: []
          #perPage: 15
          +exists: true
          +wasRecentlyCreated: false
          #attributes: array:8 [
            "id" => "1"
            "user_id" => "1"
            "name" => "Sint illo eveniet sed eaque animi ratione."
            "type" => "outdoor"
            "grow_medium" => "soiless"
            "published_at" => "2020-07-30 18:14:47"
            "created_at" => "2020-07-30 18:14:47"
            "updated_at" => "2020-07-30 18:14:47"
          ]
          #original: array:14 [
            "id" => "1"
            "user_id" => "1"
            "name" => "Sint illo eveniet sed eaque animi ratione."
            "type" => "outdoor"
            "grow_medium" => "soiless"
            "published_at" => "2020-07-30 18:14:47"
            "created_at" => "2020-07-30 18:14:47"
            "updated_at" => "2020-07-30 18:14:47"
            "pivot_product_id" => "1"
            "pivot_diary_id" => "1"
            "pivot_score" => "1"
            "pivot_body" => "this is my comment"
            "pivot_created_at" => "2020-07-30 18:14:47"
            "pivot_updated_at" => "2020-07-30 18:14:47"
          ]
          #changes: []
          #classCastCache: []
          #dates: []
          #dateFormat: null
          #dispatchesEvents: []
          #observables: []
          #relations: array:3 [
            "pivot" => Illuminate\Database\Eloquent\Relations\Pivot {#4367
              +incrementing: false
              #guarded: []
              #connection: "sqlite"
              #table: "product_ratings"
              #primaryKey: "id"
              #keyType: "int"
              #with: []
              #withCount: []
              #perPage: 15
              +exists: true
              +wasRecentlyCreated: false
              #attributes: array:6 [
                "product_id" => "1"
                "diary_id" => "1"
                "score" => "1"
                "body" => "this is my comment"
                "created_at" => "2020-07-30 18:14:47"
                "updated_at" => "2020-07-30 18:14:47"
              ]
              #original: array:6 [
                "product_id" => "1"
                "diary_id" => "1"
                "score" => "1"
                "body" => "this is my comment"
                "created_at" => "2020-07-30 18:14:47"
                "updated_at" => "2020-07-30 18:14:47"
              ]
              #changes: []
              #casts: []
              #classCastCache: []
              #dates: []
              #dateFormat: null
              #appends: []
              #dispatchesEvents: []
              #observables: []
              #relations: []
              #touches: []
              +timestamps: true
              #hidden: []
              #visible: []
              #fillable: []
              +pivotParent: App\Product {#4352
                +fillable: array:5 [
                  0 => "supplier_id"
                  1 => "name"
                  2 => "long_desc"
                  3 => "active"
                  4 => "release_date"
                ]
                #with: array:1 [
                  0 => "likes"
                ]
                #appends: array:2 [
                  0 => "likesCount"
                  1 => "isLiked"
                ]
                #casts: array:4 [
                  "supplier_id" => "integer"
                  "active" => "boolean"
                  "dry_weight" => "integer"
                  "wet_weight" => "integer"
                ]
                #connection: "sqlite"
                #table: "products"
                #primaryKey: "id"
                #keyType: "int"
                +incrementing: true
                #withCount: []
                #perPage: 15
                +exists: false
                +wasRecentlyCreated: false
                #attributes: []
                #original: []
                #changes: []
                #classCastCache: []
                #dates: []
                #dateFormat: null
                #dispatchesEvents: []
                #observables: []
                #relations: []
                #touches: []
                +timestamps: true
                #hidden: []
                #visible: []
                #guarded: array:1 [
                  0 => "*"
                ]
                +mediaConversions: []
                +mediaCollections: []
                #deletePreservingMedia: false
                #unAttachedMediaLibraryItems: []
              }
              #foreignKey: "product_id"
              #relatedKey: "diary_id"
            }
            "user" => App\User {#4376
              #fillable: array:6 [
                0 => "is_admin"
                1 => "name"
                2 => "email"
                3 => "password"
                4 => "api_token"
                5 => "avatar"
              ]
              #with: array:1 [
                0 => "media"
              ]
              #appends: array:1 [
                0 => "thumbAvatarUrl"
              ]
              #hidden: array:2 [
                0 => "password"
                1 => "remember_token"
              ]
              #casts: array:2 [
                "is_admin" => "boolean"
                "email_verified_at" => "datetime"
              ]
              #connection: "sqlite"
              #table: "users"
              #primaryKey: "id"
              #keyType: "int"
              +incrementing: true
              #withCount: []
              #perPage: 15
              +exists: true
              +wasRecentlyCreated: false
              #attributes: array:10 [
                "id" => "1"
                "is_admin" => "0"
                "name" => "Marcus Prohaska"
                "email" => "[email protected]"
                "email_verified_at" => "2020-07-30 18:14:47"
                "password" => "yIXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi"
                "api_token" => null
                "remember_token" => "ps9PxiqFLk"
                "created_at" => "2020-07-30 18:14:47"
                "updated_at" => "2020-07-30 18:14:47"
              ]
              #original: array:10 [
                "id" => "1"
                "is_admin" => "0"
                "name" => "Marcus Prohaska"
                "email" => "[email protected]"
                "email_verified_at" => "2020-07-30 18:14:47"
                "password" => "yIXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi"
                "api_token" => null
                "remember_token" => "ps9PxiqFLk"
                "created_at" => "2020-07-30 18:14:47"
                "updated_at" => "2020-07-30 18:14:47"
              ]
              #changes: []
              #classCastCache: []
              #dates: []
              #dateFormat: null
              #dispatchesEvents: []
              #observables: []
              #touches: []
              +timestamps: true
              #visible: []
              #guarded: array:1 [
                0 => "*"
              ]
              #rememberTokenName: "remember_token"
              +mediaConversions: []
              +mediaCollections: []
              #deletePreservingMedia: false
              #unAttachedMediaLibraryItems: []
            }
          ]
          #touches: []
          +timestamps: true
          #hidden: []
          #visible: []
          #guarded: array:1 [
            0 => "*"
          ]
          +mediaConversions: []
          +mediaCollections: []
          #deletePreservingMedia: false
          #unAttachedMediaLibraryItems: []
        }
      ]
    }
  ]
}

The problem is I need to paginate these results but since its already a collection laravel will not allow you to easily do this, could I possibly get by with a HasManyThrough on the $supplier->ratings() then I should be able to paginate that?

0 likes
6 replies
jlrdw's avatar

You can just show the product and underneath the product paginate the ratings. Or are you showing many products here with their ratings. Have you tried using regular paginate with the results.

And why aren't you using orderBy.

MichalOravec's avatar

Why not just do this in the controller?

$ratings = $product->ratings()->with('user')->latest()->paginate(15);
1 like
datarecall's avatar

@michaloravec @jlrdw the problem is that this is in the suppliers model/level and a supplier has many products which is why I thought I could maybe use HasManyThrough

$supplier->products()->with('ratings.user')->get()->pluck('ratings')->sortByDesc('created_at');

but this is returning a collection and you can't paginate a collection you can only paginate an eloquent query.

MichalOravec's avatar

@datarecall When you add this to the boot method of AppServiceProvider

use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;

Collection::macro('paginate', function ($perPage, $total = null, $page = null, $pageName = 'page') {
    $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);

    return new LengthAwarePaginator($this->forPage($page, $perPage), $total ?: $this->count(), $perPage, $page, [
        'path' => LengthAwarePaginator::resolveCurrentPath(),
        'pageName' => $pageName,
    ]);
});

Then you can paginate on the collection, but it's not good way.

datarecall's avatar

@michaloravec I tried to do has many through but could retrieve the right results is this possible do you think?

Please or to participate in this conversation.