Mastering Eloquent: Simplify Access to Latest and Oldest Related Models

Mastering Eloquent: Simplify Access to Latest and Oldest Related Models

In the world of Laravel and Eloquent, dealing with relationships is a common task. But what if you need to consistently retrieve the most recent or the oldest related model? Enter Laravel's latestOfMany() and oldestOfMany() methods – powerful tools that simplify this process and make your code more expressive.

Understanding Latest and Oldest Relationships

These methods work with the hasOne relationship type, allowing you to define a relationship that always points to the latest or oldest related model. This is particularly useful in scenarios like retrieving a user's most recent order or the first comment on a post.

Basic Usage

Let's look at how to implement these methods:

class User extends Model
{
    public function latestOrder(): HasOne
    {
        return $this->hasOne(Order::class)->latestOfMany();
    }

    public function firstOrder(): HasOne
    {
        return $this->hasOne(Order::class)->oldestOfMany();
    }
}

With these relationships defined, you can easily access the latest or oldest order:

$user = User::find(1);
$latestOrder = $user->latestOrder;
$firstOrder = $user->firstOrder;

Custom Sorting Criteria

By default, latestOfMany() and oldestOfMany() use the model's primary key for sorting. However, you can specify a different column:

public function mostExpensiveOrder(): HasOne
{
    return $this->hasOne(Order::class)->ofMany('total', 'max');
}

Real-World Examples

Product Pricing: Retrieve the highest price a product has ever had:

class Product extends Model
{
    public function highestPrice(): HasOne
    {
        return $this->hasOne(PriceHistory::class)->ofMany('price', 'max');
    }
}

User Activity: Get the user's first and last login:

class User extends Model
{
    public function firstLogin(): HasOne
    {
        return $this->hasOne(Login::class)->oldestOfMany();
    }

    public function lastLogin(): HasOne
    {
        return $this->hasOne(Login::class)->latestOfMany();
    }
}

Blog Comments: Retrieve the most recent comment on a post:

class Post extends Model
{
    public function latestComment(): HasOne
    {
        return $this->hasOne(Comment::class)->latestOfMany();
    }
}

By leveraging latestOfMany(), oldestOfMany(), and ofMany(), you can create more expressive and efficient Eloquent models. These methods not only simplify your code but also make it more intuitive to work with time-based or comparative relationships.

If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!

Subscribe to Harris Raftopoulos

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe