title: How to retrieve products of a nested category using Many-to-Many relationship in Laravel and order the result?
body: <p>I want to retrieve products of the selected category, as well as sub-categories and I may even need to order them according to price or date. Please let me know what changes should be made to the controller!</p>
  
  <p>I am using a Many to Many Relationship for the 2 tables: Categories and Products, and a category_product to relate both.</p>
  
  <p><strong>Example</strong></p>
  
  <p>(Not all categories have sub-categories)</p>
  
  <p>Gifts</p>
  
  <p>Books</p>
  
  <p>Toys</p>
  
  <ul>
  <li><p>Boys</p></li>
  <li><p>Girls</p></li>
  </ul>
  
  <p>Phone</p>
  
  <ul>
  <li><p>Samsung</p></li>
  <li><p>Nokia</p></li>
  </ul>
  
  <p>If a user clicks Phone, all products of the category 'Phone', 'Samsung' or 'Nokia' should appear!</p>
  
  <p><strong>Database</strong></p>
  
  <pre><code>Products: id, name, price, created_at
  </code></pre>
  
  <pre><code>Categories: id, name, slug, parent_id, sorting_order, created_at
  </code></pre>
  
  <pre><code>category_product: id, category_id, product_id
  </code></pre>
  
  <p><strong>Code:</strong></p>
  
  <p>Category Model:</p>
  
  <pre><code>class Category extends Model
  {
      public function products()
      {
          return $this-&gt;belongsToMany('App\Product');
      }
  
      public function parent()
      {
          return $this-&gt;belongsTo('App\Category', 'parent_id');
      }
  
      public function children()
      {
          return $this-&gt;hasMany('App\Category', 'parent_id');
      }
  }
  </code></pre>
  
  <p>Product Model</p>
  
  <pre><code>class Product extends Model
  {
      public function categories()
      {
          return $this-&gt;belongsToMany('App\Category');
      }
  }
  </code></pre>
  
  <pre><code>class ProductController extends Controller {
  
      public function index($slug, Request $request)
      {
          if ( ! isset($_GET['sortBy']))
          {
              $category = Category::where('slug', $slug)-&gt;with('products')-&gt;first();
  
              if ( ! $category)
              {
                  abort(404, 'Page not found');
              }
          }
          else
          {
              $slug = $request-&gt;segments()[1];
              $products = Category::where('slug', $slug);
              switch ($request-&gt;sortBy)
              {
                  case 'latest':
                      $category = $products-&gt;with(['products' =&gt; function ($q) {
                          $q-&gt;orderBy('created_at', 'desc');
                      }])-&gt;first();
                      break;
                  case 'asc':
                      $category = $products-&gt;with(['products' =&gt; function ($q) {
                          $q-&gt;orderBy('price', 'asc');
                      }])-&gt;first();
                      break;
                  case 'desc':
                      $category = $products-&gt;with(['products' =&gt; function ($q) {
                          $q-&gt;orderBy('price', 'desc');
                      }])-&gt;first();
                      break;
                  default:
                      $category = $products-&gt;with('products')-&gt;first();
                      break;
              }
          }
  
          return view('products', compact('category'));
      }
  }
  </code></pre>
  
  <p>View</p>
  
  <pre><code>&lt;form id="sortProducts" class="form-inline" method="get"&gt;
     {{ csrf_field() }}
     &lt;label for="sortBy"&gt;Sort By:&lt;/label&gt;
     &lt;select name="sortBy" id="sortBy"&gt;
        &lt;option value="latest"&gt;Latest&lt;/option&gt;
        &lt;option value="asc"&gt;Price Low to Hight&lt;/option&gt;
        &lt;option value="desc"&gt;Price High to Low&lt;/option&gt;
     &lt;/select&gt;
  &lt;/form&gt;
  
  @foreach($category-&gt;products as $product)
      &lt;div class="product"&gt;
          &lt;img border="0" src="{{Voyager::image($product-&gt;image)}}" alt="{{$product-&gt;name}}"&gt;
          &lt;div class="product-name"&gt;{{$product-&gt;name}}&lt;/div&gt;
          &lt;div class="product-price"&gt;${{$product-&gt;price}}&lt;/div&gt;
      &lt;/div&gt;
  @endforeach
  </code></pre>
  
  <p>I am using Laravel Version 6.2 along with Voyager Version 1.3.</p>