Search code examples
laraveleloquentlaravel-5.3

Laravel Scope using different Model (has a relationship)


Trying to get a scope setup that will let me filter through one model (Properties), based on a column (name) in another model (Users).

I have a relationship setup to where a User has many properties, and a Property belongs to a user.

Right now I've tried this...

public function scopeFilterByUser($query, $user)
{
    return $query->join('users', function($join) use ($user)
    {
        $join->on('properties.user_id', '=', 'users.id')
            ->where('name', 'LIKE', '%'.$user.'%');
    });
}

which "works" except that it breaks my Accessor on the Property model.

Both the Property and User have their own tables, with columns for address, city, state, and zipcode. Only the Property has a full_address column which I'm using an accessor for like this...

public function getFullAddressAttribute($value)
{
    $address = $this->address;
    $city    = $this->city;
    $state   = $this->state;
    $zipcode = $this->zipcode;
    return $address.', '.$city.', '.$state.', '.$zipcode;
}

Both of these are in the Property model. For some reason when accessing the $property->full_address after filtering the properties with this filterByUser.. full_address is returning the combined values from the User table and not the Property table.

I'm wondering what the best way would be to set this up so I can filter Properties by the Users name. The property DOES have a user_id column, but I'm looking to filter based on user name.

It all works if I rename all of the property address fields to prop_address, prop_city, etc... but this is not ideal.

Any ideas? I've tried everything I can think of.


Solution

  • Can you try changing your scope to this :

    public function scopeFilterByUser($query, $user)
    {
      return $query->whereHas('users', function($q) use ($user) {
        $q->where('name', 'like', '%' . $user . '%');
      });
    }
    

    You can then use it as

    $properties = Property::filterByUser('name')->get();
    
    // Then
    $properties->first()->full_address
    

    Let me know in the comments if this doesn't work :)