Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Kurai's avatar
Level 4

Take 1 Record From many-to-many relationship

Good Day everyone, is there a way that i can load only 1 record from many to many relationship based on a pivot table column.

Let say i have three tables

Table 1: Address

ID: Serial
name: string

Table 2 (pivot): user_address

user_id: unsigned_int
address_id: unsigned_int
is_active: boolean

Table 3: users

id: unsigned_int
name: string

Let's say i want to retrieve a single user active address, is there a way to avoid loading all the addresses in a collection using the belongsToMany relationship? was looking for a belongsToOne result.

0 likes
3 replies
LaryAI's avatar
Level 58

Certainly! If you're using Laravel's Eloquent ORM, you can achieve this by querying the relationship with a constraint that limits the results to the active address. Here's how you can do it:

// Assuming you have a User model and an Address model set up with a many-to-many relationship

class User extends Model
{
    // ...

    public function addresses()
    {
        return $this->belongsToMany(Address::class, 'user_address')
                    ->withPivot('is_active');
    }

    public function activeAddress()
    {
        return $this->addresses()->wherePivot('is_active', true)->first();
    }
}

// Then you can retrieve the active address for a user like this:

$user = User::find($userId); // Replace $userId with the actual user ID
$activeAddress = $user->activeAddress();

// If you need to do this in a query for multiple users, you can use a subquery:

$users = User::addSelect(['active_address_id' => Address::select('id')
    ->join('user_address', 'addresses.id', '=', 'user_address.address_id')
    ->whereColumn('user_address.user_id', 'users.id')
    ->where('user_address.is_active', true)
    ->limit(1)
])->get();

foreach ($users as $user) {
    // You can access the active address ID for each user with $user->active_address_id
    // To get the full address, you would need to load it separately or adjust the subquery to select more fields
}

In the activeAddress method, we're defining a custom relationship method that applies a constraint to only get the active address. We use wherePivot to apply a condition to the pivot table column is_active. The first method is then used to get the first result of the query, which is effectively the only active address for the user.

In the case where you need to retrieve the active address for each user in a list of users, you can use a subquery in the addSelect method to add the active address ID as a custom attribute to your user models. This avoids loading all addresses into a collection and allows you to work with just the active address.

Remember to replace Address::class with the actual namespace of your Address model if it's different. Also, ensure that your pivot table and foreign key names match the ones used in your database schema.

Kurai's avatar
Level 4

Thats great larry, but i am trying to retrieve a list of users and their active address without loading each user address individually. Also the addSelect would only allow me to return a single column.

shadkamel's avatar

i hope this help

// User model
class User extends Model
{
    public function addresses()
    {
        return $this->belongsToMany(Address::class, 'user_address')
                    ->withPivot('is_active');
    }

    public function activeAddress()
    {
        return $this->addresses()->wherePivot('is_active', true)->first();
    }
}

// Address model
class Address extends Model
{
    // Address model methods...
}

// Retrieving the active address for a specific user
$user = User::find($userId); // Replace $userId with the actual user ID
$activeAddress = $user->activeAddress();

Please or to participate in this conversation.