You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CodeIgniter能否实现含多级分类的自定义URL路由?

Absolutely you can pull this off—let's walk through how to handle multi-level category URLs in CodeIgniter without breaking your existing controllers or resorting to messy cross-controller calls.

The Core Idea

CodeIgniter routes match top-to-bottom, so we'll prioritize explicit controller routes first, then add a targeted rule for multi-level category/post URLs. We'll use a dedicated resolver controller to handle the URL parsing and database lookup, instead of forcing the post controller to handle all edge cases.

Step 1: Reorder Your Routes

First, define all your explicit controller routes at the top of application/config/routes.php. This ensures they don't get overridden by broader rules later:

// Keep your existing explicit routes FIRST
$route['auth/login'] = 'auth/login';
$route['admin/dashboard'] = 'admin/dashboard';
$route['about'] = 'pages/about';
// ... add any other single or fixed-path routes here

// Default controller (keep this at the bottom)
$route['default_controller'] = 'home';

Step 2: Add the Multi-Level Category/Post Route

Next, add a precise regex route that matches only URLs with multi-level categories followed by a post slug. This avoids catching single-segment URLs (like your other controllers):

// Match URLs like /category1/category2/post-slug
// Regex breakdown:
// - (.+) = captures all preceding category segments (supports / separators)
// - ([^/]+) = captures the final post slug (no / allowed)
$route['(.+)/([^/]+)'] = 'url_resolver/get_post_by_path';

For extra strictness (if your slugs only use letters, numbers, and hyphens), use this more targeted regex:

$route['([a-z0-9-]+(?:/[a-z0-9-]+)*)/([a-z0-9-]+)'] = 'url_resolver/get_post_by_path';

Step 3: Create the URL Resolver Controller

Make a new controller application/controllers/UrlResolver.php to handle parsing the URL, validating categories, and fetching the post:

<?php
class UrlResolver extends CI_Controller {
    public function __construct() {
        parent::__construct();
        $this->load->database();
        $this->load->model('post_model'); // Assumes you have a post model
        $this->load->model('category_model'); // Assumes you have a category model
    }

    public function get_post_by_path() {
        // Split the URL into segments
        $segments = $this->uri->segment_array();
        $post_slug = array_pop($segments); // Last segment is the post
        $category_slugs = $segments; // Remaining segments are categories

        // Validate the category path exists in the database
        $category_id = $this->category_model->get_category_id_from_path($category_slugs);
        if (!$category_id) {
            show_404();
            return;
        }

        // Fetch the post that belongs to this category and matches the slug
        $post = $this->post_model->get_post_by_slug_and_category($post_slug, $category_id);
        if (!$post) {
            show_404();
            return;
        }

        // Load your post view with the data (no cross-controller calls needed)
        $data['post'] = $post;
        $this->load->view('post/detail', $data);
    }
}

Step 4: Add Helper Methods to Your Models

Add these methods to your category and post models to handle the database lookups efficiently:

Category Model (application/models/Category_model.php)

public function get_category_id_from_path($slugs) {
    $current_parent_id = null;
    foreach ($slugs as $slug) {
        $this->db->where('slug', $slug);
        if ($current_parent_id !== null) {
            $this->db->where('parent_id', $current_parent_id);
        } else {
            $this->db->where('parent_id', 0); // Adjust if your top-level categories use a different parent value
        }
        $category = $this->db->get('categories')->row();
        
        if (!$category) {
            return false;
        }
        $current_parent_id = $category->id;
    }
    return $current_parent_id;
}

Post Model (application/models/Post_model.php)

public function get_post_by_slug_and_category($slug, $category_id) {
    $this->db->join('post_category', 'posts.id = post_category.post_id');
    $this->db->where('posts.slug', $slug);
    $this->db->where('post_category.category_id', $category_id);
    return $this->db->get('posts')->row();
}

Key Notes

  • Route Order Matters: Always put explicit routes first—CodeIgniter stops at the first match it finds.
  • Avoid Cross-Controller Calls: By using a resolver controller and reusing model logic, you stay within CodeIgniter's best practices.
  • 404 Handling: Don't forget to return 404 pages for invalid category paths or non-existent posts.
  • Performance: If you have deep category trees, consider optimizing the category lookup with a recursive database query (like MySQL's WITH RECURSIVE) to reduce multiple database hits.

内容的提问来源于stack exchange,提问作者Pipe Soto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:39:45