如何设置动态路由以在 CodeIgniter 中使用 slug?
Posted
技术标签:
【中文标题】如何设置动态路由以在 CodeIgniter 中使用 slug?【英文标题】:How to set dynamic route to use slug in CodeIgniter? 【发布时间】:2013-02-28 07:38:33 【问题描述】:假设我有一个名为
的控制器页面
还有一个方法
slug_on_the_fly
public function slug_on_the_fly($slug)
我的路线会是什么样子?
例如对于博客控制器,这很容易:
$route['blog/(:any)'] = 'pages/slug_on_the_fly/$1';
然后http://localhost/blog/name-of-the-article
效果很好
但是,如果我想在没有blog
的情况下这样做,例如
http://localhost/name-of-the-article
或 http://localhost/another-article-blablabla
如何做到这一点并且不破坏其他路线,例如$route['friends'] = 'users';
或 $route['about-us'] = 'pages/about_us';
?
因为如果我这样做:
$route['(:any)'] = 'pages/slug_on_the_fly/$1';
它可能会毁掉其他一切,还是?
【问题讨论】:
知道如何处理这种情况吗? 把“catch-all”路由放在最后,如果没有找到任何东西,请确保该方法使用error_404()
。
你能说得更具体点吗?如果我把$route['(:any)'] = 'pages/slug_on_the_fly/$1';
放在最后,之前的一切都会搞砸
路由是按顺序检查的,所以(:any)
不会匹配,除非它之前没有匹配的其他路由。
路由匹配短路。 first 匹配的路由获胜,而不是 last 匹配的路由!即使它没有短路,解决方法是将(:any)
作为 first 路由,对吗?
【参考方案1】:
这对你有帮助
$route['controllerName/(:any)] = "controllename/method/slug";
【讨论】:
【参考方案2】:也许这会对你有所帮助。
$route['controllerName/([^/]+)/([^/]+)'] = "index/author/$1/$2";
【讨论】:
【参考方案3】:使用404 override reserved route 控制器/方法。如果不存在有效的控制器/路由,则将调用此方法。作为一个包罗万象的作品非常棒。
【讨论】:
【参考方案4】:网址按以下顺序路由:
$route
(routes.php) 中的显式路由按顺序检查。
尝试使用隐式路由 [folder/]controller/methodname/args...
作为后备。
如果有少量已知的显式路由,您可以将它们添加到$route
:
$route['(my-slug|my-other-slug|my-third-slug)'] = 'pages/slug_on_the_fly/$1'
(路由键实际上被解析为正则表达式,:any
和 :num
被重写为 .+
和 [0-9]+
。)
如果你有大量这样的路由(可能不是一个好主意,顺便说一句!)你可以在$route
的end添加一个通配符路由:
$route['([^/]+)/?'] = 'pages/slug_on_the_fly/$1'
这里的正则表达式的意思是“任何没有斜杠的网址(可能最后一个除外)”。如果您有任何其他限制,您可以改进它以描述您的 slug 格式。 (一个好的是[a-z0-9-]+
。)如果你的控制器在数据库中找到了slug,你就完成了。如果没有,它必须提供 404。
但是,您放弃了一些隐式路由的可能性,因为 Codeigniter 没有为控制器“放弃”返回路由器的路由提供任何方式。例如,如果您有一个名为 'foo' 的控制器,并且您希望像 /foo
这样的 url 路由到 Foo::index()
,您必须为这种情况添加一个显式路由,因为它会被此路由捕获并发送到 @987654334 @ 反而。 一般来说,你不应该有也是控制器类名的 slug!这就是为什么你应该有非常少量的这些 url-slug,如果你有的话!
如果你有两者大量这些显式路由并且你不愿意遵守这些隐式路由限制,你可以尝试将它们添加到$route
动态:
-
制作一个
routes_extra.php
文件,最后包含routes.php
。在保存页面或构建/部署网站时为其写入新路由。
子类 Router.php
并添加新的路由层。
添加一个 pre_system
钩子来添加路由。
我相信还有其他方法。
【讨论】:
谢谢,我正在使用带有 codeigniter 的 HMVC,$route['([^/]+)/?'] = 'pages/slug_on_the_fly/$1'
似乎正在工作。但我需要做更多的测试。现在,谢谢。【参考方案5】:
您可以使用数据库驱动的路线。
将表 blog_slugs
添加到您的 mysql 数据库中:
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;
将 application/config/routes.php 中的代码替换为以下代码:
$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;
您所要做的就是在创建博客条目时创建一条记录,然后就完成了:
INSERT INTO `blog_slugs` (`slug`) VALUES ('name-of-the-article');
【讨论】:
谢谢,有趣的概念。但是当我有例如10 000 篇文章。会不会很慢?就我而言,这没什么大不了的。我有最大。 50 页/文章。但我只是好奇;) 您可以缓存数据库查询输出。我使用了它的扩展版本来处理我的所有路由,并使用缓存文件读取速度很好(无论如何对我来说)。我用github.com/philsturgeon/codeigniter-cache【参考方案6】:假设你有 3 个控制器,而不是页面控制器,那么控制器 1、控制器 2 和控制器 3,
$route['^(?!controller1|controller2|controller3).*'] = 'pages/slug_on_the_fly/$1';;
【讨论】:
以上是关于如何设置动态路由以在 CodeIgniter 中使用 slug?的主要内容,如果未能解决你的问题,请参考以下文章