Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel multiple whereHas criteria for relationship

I have two tables - contacts and visits:

Contacts Table

id    | name          
----- | -------
1     | Joe
2     | Sally

Visits Table

id    | contact_id | pathname  | referrer                
----- | -------    | -------   | -------
1     | 1          | about     | google
2     | 1          | pricing   | null
3     | 1          | signup    | null
4     | 2          | about     | null
5     | 2          | signup    | null

Using eloquent, I would like to retrieve all contacts that have a both a pathname = 'signup' AND a referrer = 'google'.

What I've got so far is:

Contact::whereHas('visits', function($query) {
    $query->where('pathname','=','signup');
})
->orWhereHas('visits', function($query) {
    $query->where('referrer','=','google');
})
->get();

Which properly retrieves all contacts that have visited either the pricing OR signup page.

However, this example would also retrieve Sally (from the example table above), since she visited signup, but was not referred by google. I need a way to only retrieve Joe, who was both referred by google and visited pricing.

Any ideas? Thanks in advance!

like image 759
user3415951 Avatar asked Oct 04 '14 16:10

user3415951


2 Answers

You can use:

Contact::whereHas('visits', function($query) {
    $query->where('pathname','=','signup');
})
->whereHas('visits', function($query) {
    $query->where('referrer','=','google');
})
->get();
like image 76
Marcin Nabiałek Avatar answered Nov 15 '22 23:11

Marcin Nabiałek


A refined version of the code above:

Contact::whereHas('visits', function($query) {
    $query->where('pathname','signup')->where('referrer','google');
})->get();

Several noteworthy points:

  1. You can chain where() clauses within a closure.
  2. The default operator for a where clause is =, so you can omit it.
  3. Use multiple whereHas() clauses, when accessing multiple related models.
like image 24
Darren Murphy Avatar answered Nov 15 '22 21:11

Darren Murphy