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

