How to paginate a "has many" relationship that is ordered?
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# How to Paginate a "has many" Relationship That Is Ordered: A Deep Dive into Eloquent Pagination
As developers working with Laravel and Eloquent, we frequently encounter scenarios where we need to retrieve subsets of related data. One common requirement is paginating these relationships. When you try to chain methods like `orderBy()` and `paginate()` directly onto a relationship definition in your model, you run into an error because of how Eloquent structures its relation methods.
This post will diagnose the issue you are facing with paginating ordered "has many" relationships and provide the correct, idiomatic Laravel solution.
## The Problem: Why the Error Occurs
You are attempting to define a relationship that includes ordering and pagination directly within the model:
```php
class Category extends Model
{
public function apps()
{
return $this->hasMany('App\App')->orderBy('current_price', 'asc')->paginate(10); // This causes an error
}
}
```
The error you receiveâ`Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation`âis not a failure of the database query itself, but a constraint imposed by the Eloquent framework. Relationship methods (like `apps()`) are designed to return an *Eloquent Relation object* (e.g., `HasMany`), which represents the potential relationship structure. They are not designed to execute a final, paginated query directly.
Pagination is not a property of the relationship definition; it is a property of the **query** that fetches the data. The relationship method's job is only to define *which* other models exist and how they relate.
## The Solution: Separating Concerns (Model vs. Controller)
The correct approach is to separate the definition of the relationship (which happens in the Model) from the execution of the query, including filtering and pagination (which happens in the Controller). This separation adheres to good architectural principles, making your code cleaner, more reusable, and easier to maintainâa key principle when building robust applications with Laravel.
### Step 1: Define the Relationship Correctly (The Model)
In your `Category` model, define the relationship simply to establish the connection and apply the ordering constraint *within* the query builder context.
```php
// app/Models/Category.php
class Category extends Model
{
public function apps()
{
// Define the basic hasMany relationship first.
return $this->hasMany('App\App');
}
}
```
### Step 2: Apply Ordering and Pagination (The Controller)
Now, when you need to retrieve these categories along with their ordered, paginated apps, you apply the constraints directly to the query builder in your controller. This allows Eloquent to correctly construct the necessary SQL query for pagination.
```php
// app/Http/Controllers/CategoryController.php
use App\Models\Category;
class CategoryController extends Controller
{
public function index()
{
// Retrieve categories, eager-loading their apps, applying ordering, and then paginating the results.
$categories = Category::with('apps')
->orderBy('current_price', 'asc') // Ordering applied to the main category query (if necessary)
->paginate(10);
return view('categories.index', compact('categories'));
}
}
```
### Alternative: Ordering within Nested Queries
If you specifically need the pagination *within* the context of a specific parent category, you apply the constraints to the relationship call itself, which is perfectly valid as it returns a standard `Relation` object that can be queried further.
For example, if you only want the apps for a specific category, ordered and paginated:
```php
// In your controller or another scope where you access a Category model instance:
$category = Category::find(1);
// Now, query the relationship with constraints and pagination applied to the related set.
$orderedApps = $category->apps()
->orderBy('current_price', 'asc')
->paginate(10);
```
## Conclusion
The core takeaway is that Eloquent relationships define *structure*, while controllers or query builders define *execution*. By avoiding placing execution methods like `paginate()` directly into the relationship definition, you ensure your code remains idiomatic and avoids framework errors. Always focus on letting the Model define the structure (`hasMany`, `belongsTo`), and let the Controller handle the dynamic querying, ordering, and pagination required for data presentation. For more advanced filtering needs, exploring Eloquent Scopes can further streamline these complex relationships, offering a powerful way to encapsulate reusable query logic across your application, as demonstrated by the extensive features available in the Laravel ecosystem found at [https://laravelcompany.com](https://laravelcompany.com).