Question

Please help me make this query in eloquent. A business can have many categories.

SELECT b.* 
FROM   businesses b 
       INNER JOIN categorybusiness cb 
               ON b.id = cb.business_id 
       INNER JOIN category c 
               ON cb.category_id = c.id 
WHERE  b.location LIKE '%query1%' 
       AND b.location LIKE '%query2%' 
       AND c.name LIKE '%query3%' 
       AND c.name LIKE '%query4%' 

my tables are.. businesses - contain the location column and a pivot table for category and business..

UPDATE: so i used this query...

$business5 = Business::WhereHas('categories', function($q) use($category,$query1)
    {
          $q->whereRaw("name like '%$category%' or businesses.name like '%$category%' $query1");         
    })->get();

$query1 looks like this but in a loop.

     $query1 .= " and businesses.address1 like '%$string%'"; 

It's working fine but can someone help me make a "MATCH AGAINST" statement in eloquent from this.

Was it helpful?

Solution

For making an Eloquent query you need to setup relationship and to create a many-to-many relationship you need to build the relationship like this in both models:

The Business model:

class Business extends Eloquent {
    //...
    public function categories()
    {
        return $this->belongsToMany('Caregory');
    }
}

The Category model:

class Category extends Eloquent {
    //...
    public function businesses()
    {
        return $this->belongsToMany('Business');
    }
}

The Eloquent query (You already have a pivot table):

$businesses = Business::with(array('categories' => function($q) use ($query3, $query4) {
    $q->where('categories.name', 'LIKE', '%'. $query3 .'%')
      ->where('categories.name', 'LIKE', '%'. $query4 .'%');
}))->where('businesses.location', 'like', '%'. $query1 .'%')
   ->where('businesses.location', 'like', '%'. $query2 .'%')
   ->get();

To check the result just use dd($businesses); and examine the collection so you'll get the idea about how you can loop them in your view. Basically, $businesses will contain a collection and each $business model in the collection will contain another collection of $categories, so loop could be something like this:

@foreach($businesses as $business)
    {{ $business->propertyname }}
    @foreach($business->categories as $category)
        {{ $category->propertyname }}
    @endforeach
@endforeach

OTHER TIPS

Assuming you have Business moel setup, this is exactly the query you wanted, as eager loading suggested by @WereWolf won't do the job here (where clauses on joined tables vs on 2 separate queries):

Business::from('businesses as b')
  ->join('categorybusiness as cb', 'b.id', '=', 'cb.business_id')
  ->join('category as c', 'c.id', '=', 'cb.category_id')
  ->where('b.location', 'like', "%$query1%")
  ->where('b.location', 'like', "%$query2%")
  ->where('c.name', 'like', "%$query3%")
  ->where('c.name', 'like', "%$query4%")
  ->get(['b.*']);

There is also another way using whereHas method as long as you have belongsToMany relations setup correctly

Business::whereHas('categories', function ($q) use ($query3, $query4) {
    $q->where('categories.name', 'like', "%$query3%")
      ->where('categories.name', 'like', "%$query4%");
})->where('businesses.location', 'like', "%$query1%")
    ->where('businesses.location', 'like', "%$query2%")
    ->get();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top