1

The question seems realy simple, but I can't figure it out... How do you achieve slug-based dynamic pages with categories in Laravel 5.1?

Something like mywebsite.com/category/sub-category/my-page

I know that Route::get('/{slug}') gives the "slug" as identifier, but the problem is that the page could be situated in mywebsite.com/category/my-page, so if set the route to something like Route::get('/{category}/{subcategory}/{page}') it will not work for the second example.

I was thinking about making 3 routes like

Route::get('/{category}/{subcategory}/{page}')
Route::get('/{category}/{page}')
Route::get('/{page}')

And then the controller to receive ($category = null, $subcategory = null, $page = null) And in the controller something like

if (!$page)
    $page = $subcategory;

if (!$page)
    $page = $category;

Is there another, cleaner way to achieve this? Because here we have only 2 category routes, but there could be 3, 5 or more?

Ivan Milanov
  • 196
  • 1
  • 10
  • This seems like the product of poor design. If you don't need the category and subcategory to show a page, don't force your users to go through it. If you are somehow stuck with these routes, use `request()->page` to get the page rather than fumble with the function parameters. – user1669496 Dec 01 '15 at 17:19
  • i wonder if you could use `Route::controller` with a *dynamic* method like, `public function getSomePage(Request $request)` then do a manual approach over `$request->segments()` - didn't tried this, nevertheless, reading [the doc](http://laravel.com/api/5.1/Illuminate/Http/Request.html) might give some insight. **ps.** `route::controller` although having a predefined parameter, ie. `getSomePage($category, $slug)` in `route::list` still being shown as `SomePage/{one?}/{two?}/.../{five?}` – Bagus Tesa Dec 01 '15 at 21:01
  • @Ivan Milanovm , if use `Route::get('/{page}')` how show other url? example `/user` or ... the urls that not `page` . – Mostafa Norzade Jun 03 '19 at 20:16

1 Answers1

0

Ok, so basically you want to have a categories of categories and able to access posts through those categories. I assume you had a model like this:

class Category extends Model
{
  public function SubCategories()
  {
    return $this->hasMany('Category', 'parent_id', 'id');
  }
  public function ParentCategory()
  {
    return $this->belongsTo('Category', 'parent_id', 'id);
  }
  public function Page()
  {
    return $this->hasMany('Page', 'category_id', 'id');
  }
}

then on create a controller to retrieve posts

class PageLoaderController extends Controller
{
   //assumes you want to run this via root url (/)
   public function getIndex(Requests $request)
   {
     //this practically get you any parameter after public/ (root url)
     $categories = $request->segments();
     $countSeg   = count($categories);
     $fcategory  = null;
     $fpage      = null;
     for($i = 0; $i < $countSeg; $i++)
     {
       //this part of iteration is hypothetical - you had to try it to make sure it had the desired outcome
       if(($i + 1) == $countSeg)
       {
         //make sure fcategory != null, it should throw 404 otherwise
         //you had to add code for that here
         $fpage = $fcategory->Page()->where('slug', $categories[$i])->firstOrFail();
       }
       elseif($i == 0)
       {
         //find initial category, if no result, throw 404
         $fcategory = Category::where('slug', $categories[0])->firstOrFail();
       }
       else
       {
         //take it's child category if possible, otherwise throw 404
         $fcategory = $fcategory->SubCategories()->where('slug', $categories[$i])->firstOrFail()
       }
     }
     //do something with your $fpage, render it or something else
   }
}

Then add to your route.php:

Route::controller('/','PageLoaderController', [
                  'getIndex' => 'home'
                  ]);

That should do. However, this is a dirty approach which is i won't suggest using this thing extensively. Some of the reasons are, http get length is not limited but it's a bad practice to have it too long, this approach is not good for CRUD - go for Route::resource instead, also the loop looks painful.

Take note: Route::controller is more wild than Route::resource you had to put entries in route.php in this order Route::<http verb>, Route::resource then finally Route::controller. So far, i faced Laravel route behavior, it'll poke Route::controller even if it had no method regarding requested url and throws a NotFoundHttpException. So if you had Route::<http verb> after Route::controller laravel tend to not touch it at all.

Community
  • 1
  • 1
Bagus Tesa
  • 1,317
  • 2
  • 19
  • 42