Leandro Gamarra
Leandro Gamarra

Reputation: 151

Filter a one to many relation record result

I need to filter the results given from a one to many relation directly from the model object, but I cant find the right way. Here, the relations:

I have a User model that can subscript to many companies (company model), and a company can have many users subscripted to it, so, is a many to many relation.

In every company, this user has a personal info, so, every user, could have many profiles (profile model) one for each company that is subscripted to. So It is a one to many relation.

Imagine I want to retrieve the company that a user is currently viewing directly from the model, this, Im achieving by filtering the many to many relation:

class User extends Authenticatable
{
///
 public function obtainLoggedOnCompany()
 {
   return $this->belongsToMany('app\Company', 'user_company', 'id', 'company_id')->withPivot('selected')->wherePivot('selected', 1)  
 }

Then, if I want to return the selected company in a blade view I just call:

Auth::user()->obtainLoggedOnCompany->first();

All thanks to the withPivot and wherePivot clause.

Different is the case when I want to retrieve the registered profile of a currently selected company, I tried:

public function obtainSelectedProfile()
{
$SelectedCompany= $this->obtainLoggedOnCompany->first();

return $this->hasMany('app\Profile','user_id')->where('company_id', '=', $SelectedCompany->company_id);
}

But it throws a Trying to get property of non object Exception. Is there another way to filter one to many relations directly in the model relation function?

Iam using Laravel 5.2

Upvotes: 0

Views: 368

Answers (3)

Leandro Gamarra
Leandro Gamarra

Reputation: 151

actually, this sentence works perfectly!:

public function obtainSelectedProfile()
{
$SelectedCompany= $this->obtainLoggedOnCompany->first();

return $this->hasMany('app\Profile','user_id')->where('company_id', '=', 
$SelectedCompany->company_id);
}

My error was elswhere on my view!

Though I think Its a better practice to prepare the data on the controller before passing it to the view, because I would have to query to server every single time I want to get data from the user profile on the fly in the view.

Upvotes: 0

Shree Sthapit
Shree Sthapit

Reputation: 316

How about you do:

I assume that your Company.php model has

public function userProfile(){
return $this->hasMany('app\Profile','company_id');
}

And Try this on the controller:

    $company_id=1; //suppose the current company viewing id is 1
        $user = User::where('id',Auth::id())->with(['obtainLoggedOnCompany'=>function($query) use($company_id){
        $query->where('company_id',$company_id);
        $query->with(['company_user_profile'=>function($query){
         $query->where('user_id',Auth::id());
         $query->last();
        }]);
        //$query->last();
        }])->first();

And you can fetch the profile using:

dd($user->obtainLoggedOnCompany->company_user_profile);

Upvotes: 1

Jonathan K
Jonathan K

Reputation: 550

You can achieve this by passing variable to eager loading and updating your relationship structure. Try this

User Model:

class User extends Authenticatable
{
    ///
    public function obtainLoggedOnCompany()
    {
         return $this->belongsToMany('App\Company', 'user_company', 'user_id', 'company_id'); 
    }

}

Company Model:

class Company extends Model
{
    ///
    public function profile()
    {
        return $this->hasOne('App\Profile', 'company_id');  
    }
}

Example A use case of this:

$user_id = 1;
$user = User::where('id', $user_id)->with(['company' => function($query) use ($user_id) {

           return $query->with(['profile' => function($query2) use ($user_id) {
                                              return $query2->where('user_id', $user_id);
                                            }]);
        }])->first();
// $user variable contains user details, company details, and profile

Upvotes: 1

Related Questions