How to set dynamic route to use slug in CodeIgniter?

痴心易碎 提交于 2019-11-29 04:52:24

Urls are routed in the following order:

  1. Explicit routes in $route (routes.php) are checked in order.
  2. An implicit route [folder/]controller/methodname/args... is attempted as a fallback.

If have a small number of known explicit routes, you can just add them to $route:

$route['(my-slug|my-other-slug|my-third-slug)'] = 'pages/slug_on_the_fly/$1'

(Routes keys are really parsed as regular expressions with :any and :num are rewritten to .+ and [0-9]+.)

If you have a large number of such routes (probably not a good idea, BTW!) you can just add a wildcard route to the end of $route:

$route['([^/]+)/?'] = 'pages/slug_on_the_fly/$1'

The regex here means "any url that has no slashes (except maybe last)". You can refine this to describe your slug format if you have any other restrictions. (A good one is [a-z0-9-]+.) If your controller finds the slug in the db, you're done. If it doesn't, it must serve a 404.

However, you give up the possibility of some implicit routing as Codeigniter doesn't provide any way for a controller to "give up" a route back to the router. For example, if you have a controller named 'foo' and you want a url like /foo to route to Foo::index(), you must add an explicit route for this case because it would be caught by this route and sent to Pages::slug_on_the_fly('foo') instead. In general, you should not have slugs which are also controller class names! This is why you should have a very small number of these url-slugs, if you have any at all!

If you have both a large number of these explicit routes and you are not willing to abide by these implicit routing limitations, you can try adding them to $route dynamically:

  1. Make a routes_extra.php file which routes.php includes at the end. Write new routes to it as part of saving a page or when you build/deploy the site.
  2. Subclass Router.php and add a new routing layer.
  3. Add a pre_system hook which adds the routes.

I'm sure there are other ways.

You could use database driven routes.

Add the table blog_slugs to your MySQL database:

CREATE TABLE IF NOT EXISTS `blog_slugs` (
  `id` bigint(20) NOT NULL auto_increment,
  `slug` varchar(192) collate utf8_unicode_ci NOT NULL
  PRIMARY KEY  (`id`),
  KEY `slug` (`slug`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;

Replace the code in application/config/routes.php with the one below:

$route[ 'default_controller' ]  = 'main';
$route[ '404_override' ]        = 'error404';

require_once( BASEPATH .'database/DB'. EXT );
$db =& DB();
$query = $db->get( 'blog_slugs' );
$result = $query->result();
foreach( $result as $row )
{
    $route[ $row->slug ] = 'pages/slug_on_the_fly/$1;
}

All you would have to do then is to create a record when you create a blog entry and you're done:

INSERT INTO `blog_slugs` (`slug`) VALUES ('name-of-the-article');

Use the 404 override reserved route controller/method. If a valid controller/route doesn't exist, this method will be called. Works great as a catch-all.

Let's assume you have 3 controllers other than pages controller say controller1, controller2 and controller3 then,

$route['^(?!controller1|controller2|controller3).*'] = 'pages/slug_on_the_fly/$1';;
Jigar Patel

Maybe this will help you.

$route['controllerName/([^/]+)/([^/]+)'] = "index/author/$1/$2";
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!