Access Specific Records from HasManyThrough with Laravel's CanBeOneOfMany Support

Access Specific Records from HasManyThrough with Laravel's CanBeOneOfMany Support

Working with HasManyThrough relationships in Laravel but only need a specific record? The new CanBeOneOfMany support lets you easily access the latest, oldest, or custom-filtered model with clean, expressive syntax.

Laravel's Eloquent ORM already provided powerful ways to work with complex relationships. Now, with the addition of CanBeOneOfMany support for HasOneThrough relationships, you can elegantly retrieve a singular model from a HasManyThrough relationship based on various criteria.

Let's see how it works:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOneThrough;

class Application extends Model
{
    /**
     * Get the latest deployment for the application.
     */
    public function latestDeployment(): HasOneThrough
    {
        return $this->deployments()->one()->latestOfMany();
    }
}

Real-World Example

This feature is particularly useful when you need to access a specific record from a larger relationship set. Here's a more comprehensive example showing different scenarios:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;

class Team extends Model
{
    /**
     * Get all projects for the team.
     */
    public function projects(): HasManyThrough
    {
        return $this->hasManyThrough(
            Project::class, 
            TeamMember::class,
            'team_id',
            'team_member_id'
        );
    }
    
    /**
     * Get the most recently created project for the team.
     */
    public function latestProject(): HasOneThrough
    {
        return $this->projects()->one()->latestOfMany();
    }
    
    /**
     * Get the first project created for the team.
     */
    public function firstProject(): HasOneThrough
    {
        return $this->projects()->one()->oldestOfMany();
    }
    
    /**
     * Get the highest priority project for the team.
     */
    public function highestPriorityProject(): HasOneThrough
    {
        return $this->projects()->one()->ofMany('priority', 'max');
    }
    
    /**
     * Get the largest project by budget.
     */
    public function largestProject(): HasOneThrough
    {
        return $this->projects()->one()->ofMany([
            'budget' => 'max',
        ]);
    }
}

With these relationship methods defined, you can now easily access specific records:

$team = Team::find(1);

// Get the most recent project
$latestProject = $team->latestProject;

// Get the first project ever created
$firstProject = $team->firstProject;

// Get the highest priority project
$priorityProject = $team->highestPriorityProject;

// Get the project with the largest budget
$largestProject = $team->largestProject;

By leveraging these new relationship methods, you can write more expressive, maintainable code that clearly communicates the relationships between your models.

If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter (https://x.com/harrisrafto), Bluesky (https://bsky.app/profile/harrisrafto.eu), and YouTube (https://www.youtube.com/@harrisrafto). 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