skip to Main Content

I’m implementing category structure , some products would have one level category but other may have two or more level :

/posts/cat2/post-sulg

/posts/cat-1/sub-1/post-slug

/posts/cat-3/sub../../../post-slug

as i dont know how depth it would be and using category slugs is only for seo (i find post only by its slug) what is the best way to create a route to handle this structure?

3

Answers


  1. You can solve this with:

    Route::get('posts/{categories}', 'PostController@categories')
        ->where('categories','^[a-zA-Z0-9-_/]+$');
    

    And then in controller

    class PostController
    {
        public function categories($categories)
        {
            $categories = explode('/', $categories);
            $postSlug = array_pop($categories)
    
            // here you can manage the categories in $categories array and slug of the post in $postSlug
            (...)
        }
    
    }
    
    Login or Signup to reply.
  2. I did something similar, this in PostController.php using

    public function slug($slug) { return $this->show(Post::where('slug', @end(explode('/', $slug)))->firstOrFail()); }
    

    In routes/web.php

    Route::get ('posts/{slug}', 'PostController@slug')->name('post.slug')->where(['slug' => '^(?!((.*/edit$)|(create$))).*D+.*$']);
    Route::resource('posts', 'PostController');
    

    If you want to use the full category list as the slug, just change the slug function:

    public function slug($slug) { return $this->show(Post::where('slug', $slug)->firstOrFail()); }
    
    Login or Signup to reply.
  3. I spend many hours for researching, googing, testing to achive this and this is the most simpy way and clean way!

    You will achive this:

    www.example/ <-- Home 
    www.example/category/post 
    www.example/category/sub-category/post 
    www.example/category/sub-category/sub-cat/sub-sub-sub-cat/post
    

    Before start:

    1. Database column (slug) must be unique
    2. You must write full path in database to avoid cinficts

    Example:

    You write post about BMW tyres:

    www.example.com/bmw/tyres/10-is-the-best-tyre-for-bmw-320d
    

    So in DB slug column you save value like this:

    bmw/tyres/10-is-the-best-tyre-for-bmw-320d
    

    Steps how i slove this

    First make route

    Route::get('/{categories?}', [WebSiteController::class, 'index'])->where('categories', '^[a-zA-Z0-9-_/]+$')->name('slug');
    

    Here take care to provide ? on param. If you miss this you can’t route homepage. Category will be required!

    Second

    Create controller method

    public function index($categories = null)
    {
        // get categories in array
        $cats = explode('/', $categories);
    
        // make array to string used for slug
        $cat_slug = implode('/', $cats);
    
        // remove last url param. Used when you route only category without post
        $post = array_pop($cats);
    
        // Its simple alias (name convention) 
        $post_slug = $cat_slug;  
    
        // No url params provided? Show home page
    
        if(!$categories) {
            return view('website.homepage');
        }
    
        // Category param exist
    
        else if($categories) {
    
            // Get category based on url slug
            $category = PostCategory::where('slug', $cat_slug)->with('childrens')->first();
    
            // Here we must determine if category or post. If category not found we load post. 
    
            // Category does not exist! Load post 
            if(!$category) {
                $post = Post::where('slug', $post_slug)->first();
    
                return view('testing.post', compact('post'));
            }
            // Category founded load it and their childs
            else {
                $posts = Post::where('post_category_id', $category->id)->get();
                return view('testing.category', compact('category', 'posts'));
            }
                        
        }
            // Nothing founded! Show 404
            else {
            abort('404');
        }
    }
    

    Category Blade

    @extends('layouts.web')
    
    @section('title', $category->name)
    
    @section('content')
    
    <h1>{{ $category->name }}</h1>
    
    <ul class="list-inline">
        @foreach($category->childrens as $child)
        <li><a href="{{ url($child->slug)}}">{{$child->name}}</a></li>
        @endforeach
    </ul>
    
    @if($posts->count() > 0)
    <hr>
    <ul>
        @foreach($posts as $post)
        <li><a href="{{ url($post->slug)}}">{{$post->title}}</a></li>
        @endforeach
    </ul>
    @endif
    @endsection
    

    Post Blade

    @extends('layouts.web')
    
    @section('title', $post->title)
    
    @section('content')
    
    <h1>{{ $post->title }}</h1>
    
    @endsection
    

    Whit this you cant make mistake. Dont waste hours like me! I just provide simple example you can now have new idea!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search