title: Laravel Eloquent filter product's attributes
body: <p>I am making a filter function for products. I have 2 models: <code>Product</code> and <code>Attribute</code> (BelongsToMany relationship)</p>
  
  <p>Attributes table:</p>
  
  <pre><code>id      name
  -------------
  1       RAM
  2       HDD
  </code></pre>
  
  <p>Products table:</p>
  
  <pre><code>id      name
  -----------------
  1       Product 1
  2       Product 2
  3       Product 3
  4       Product 4
  
  </code></pre>
  
  <p>And the pivot table look like:</p>
  
  <pre><code>id      attribute_id            product_id     value
  ----------------------------------------------------
  1       1 (RAM)                 1              8GB
  2       2 (HDD)                 1              256GB
  3       1 (RAM)                 2              8GB
  4       2 (HDD)                 2              256GB
  5       1 (RAM)                 3              4GB
  6       2 (HDD)                 4              512GB
  </code></pre>
  
  <p>When filter products, user select <code>RAM =&gt; [4GB, 8GB]</code> and <code>HDD =&gt; 256GB</code>.</p>
  
  <p>I want to get products that have <code>RAM - 4GB</code> <strong>OR</strong> <code>RAM - 8GB</code> <strong>AND</strong> <code>HDD - 256GB</code>. It means product has attributes <code>RAM - 4GB, HDD - 256GB</code> <strong>AND</strong> <code>RAM - 8GB, HDD - 256GB</code> will be satisfied the filters. Compared to my above database, I will get products with ID 1 and 2 (Product 3 have <code>RAM 4GB</code> but doesn't have <code>HDD 256</code>, so doesn't count).</p>
  
  <p>Here are my code, but it doesn't work as I expected.</p>
  
  <pre><code>$products = Product::whereHas('attributes', function ($query) {
              $query-&gt;whereIn('attribute_id', [1, 2]);
              $query-&gt;whereIn('value', ['4GB', '8GB', '256GB']);
          })-&gt;get();
  </code></pre>
  
  <p>or</p>
  
  <pre><code>$products = Product::whereHas('attributes', function ($query) {
              $query-&gt;where(function ($query) {
                  $query-&gt;where('attribute_id', 1)
                      -&gt;whereIn('value', ['4GB', '8GB']);
              })-&gt;orWhere(function ($query) {
                  $query-&gt;where('attribute_id', 2)
                      -&gt;whereIn('value', ['256GB']);
              });
          })-&gt;get();
  </code></pre>