好吧,让我们把这个分开。
忽略 CodeIgniter 的保留路由。
您的路线的default_controller
和404_override
部分是不必要的。将路由与请求的 URI 进行比较以查看是否匹配。这两项不太可能出现在您的 URI 中,因为它们是 CodeIgniter 的特殊保留路由。所以让我们忘记他们吧。
$route['(?!home|activity)[A-Za-z0-9][A-Za-z0-9_-]{2,254}'] = 'view/slug/$1';
捕捉一切!
使用正则表达式,使用圆括号创建一个组()
。然后可以使用反向引用检索该组 - 在我们的例子中,$1, $2, etc.
位于路线的第二部分。您在尝试排除的第一组项目周围只有一个组,因此它无法正确捕获整个通配符。您自己已经发现了这一点,并在整个项目周围添加了一个组(好!)。
$route['((?!home|activity)[A-Za-z0-9][A-Za-z0-9_-]{2,254})'] = 'view/slug/$1';
展望?!
关于那个主题,第一组周围home|activity
实际上并不是一个传统的组,因为?!
一开始就使用了。这称为负前瞻,它是一个复杂的正则表达式功能。它被错误地使用:
如果你想匹配一些没有被其他东西跟随的东西,负前瞻是必不可少的。
我可以做的还有很多,但基本上我们一开始并不真正想要或不需要它,所以如果你愿意,我会让你探索。
为了让你的生活更轻松,我建议在路由中分离 home、activity 和其他现有控制器。CodeIgniter 将从上到下查看路由列表,一旦匹配,它就会停止检查。因此,如果您在通配符之前指定您现有的控制器,它们将匹配,并且您的通配符正则表达式可以大大简化。
$route['home'] = 'pages';
$route['activity'] = 'user/activity';
$route['([A-Za-z0-9][A-Za-z0-9_-]{2,254})'] = 'view/slug/$1';
请记住按从最具体到最少的顺序列出您的路线。通配符匹配不如完全匹配(如家庭和活动)那么具体,因此它们应该紧随其后(如下)。
现在,这就是所有复杂的东西。多一点仅供参考。
请记住,括号中的破折号-
具有特殊含义。[]
如果您想匹配文字破折号,您应该转义它们。
$route['([A-Za-z0-9][A-Za-z0-9_\-]{2,254})'] = 'view/slug/$1';
请注意,您的字符重复最小值/最大值{2,254}
仅适用于第二组字符,因此您的用户名必须至少为 3 个字符,最多为 255 个字符。仅供参考,如果您还没有意识到的话。
我看到了你自己对这个问题的回答,这很丑陋。对不起。^
和符号在$
整个前瞻过程中使用不当(一开始就不应该存在)。它可能对您正在测试它的一些用例“有效”,但它只会在未来给您带来问题和头痛。
希望现在您对正则表达式以及它们在路由过程中的匹配方式有更多的了解。
为了回答你的问题,不,你不应该在你的正则表达式的开头和结尾使用^
和$
——CodeIgniter 会为你添加它。
使用 404,卢克...
此时,您的路线已得到改进,应该可以正常工作。不过,我会把它扔在那里,你可能想考虑使用定义为的控制器/方法404_override
来处理你的通配符。这样做的主要好处是您不需要任何路由来引导通配符,或者防止通配符弄乱现有的控制器。你只需要:
$route['404_override'] = 'view/slug';
然后,您的 View::slug() 方法将检查 URI,并查看它是否是有效模式,然后检查它是否作为用户存在(毫无疑问,与您的 slug 方法现在所做的相同)。如果是这样,那么你很高兴。如果没有,那么您将抛出 404 错误。
它可能看起来不那么优雅,但效果很好。如果听起来更适合您,请试一试。