【问题标题】:codeigniter - route all uri to one special uri except some casescodeigniter - 将所有 uri 路由到一个特殊的 uri,除了某些情况
【发布时间】:2026-02-07 00:25:01
【问题描述】:

我希望我的站点的所有 uri 都路由到一个控制器。除了以 home、admin、login 或 sigun_up 开头的 uri 不会路由到那个控制器。你会怎么做?

我在想某种 reg ex,像这样

$route["到这个控制器的所有链接路由,除了以 admin、login、home 和 sign_up 开头的 uri"] = 'boss controller';

【问题讨论】:

  • 你有什么办法解决这个问题?
  • 试过但没有运气。我尝试了各种正则表达式,它们现在很乱

标签: php regex codeigniter


【解决方案1】:

我认为你不能做负路由。
但是您可以通过以下方式执行此操作:

$route['(admin|login|home|sign_up)'] = "$1";
$route['(admin|login|home|sign_up)/(:any)'] = "$1/$2";
$route['(:any)'] = "boss_controller";

【讨论】:

  • CI 级联这些路由。所以基本上,用那个代码。当转到站点内的任何 uri 时,您将获得双重路由(例如:my_site.com/home 将转到老板控制器,然后重定向到主控制器。
  • @angry_kiwi 你错了。它按照命令你写。如果匹配它不检查休息路线。你可以测试很多方式。示例1.如果你这样写$route['(admin|login|home|sign_up)'] = "$1";$route['(admin|login|home|sign_up)'] = "boss_controller";@ 987654324@ 永远不会去 boss_controller。它将首先匹配到家庭控制器。示例 2:您可以在 boss_controller 中写入 die() 并点击 my_site.com/home 它不会转到 boss_controller 并重定向。如果确实如此,它将退出您的代码。希望您能理解。
  • 理论上你是对的。但事实上,您可以通过添加访客计数挂钩来了解我的意思。让它在后控制器上运行。现在有了您提供的路由,当您打开任何页面或控制器时,钩子将计算两次访问,这意味着它会路由和重新路由。这是我使用的简单钩子类dropbox.com/s/ui1f1dgg33wd9zm/Traffic.php?dl=0
  • 我已经测试了代码。上面的路由功能可以按照你的意愿工作。并且没有post_controller 飞节为my_site.com/home 运行两次。即使您可以使用 redirect 函数进行大量重定向 post_controller 飞节对最后一个控制器执行一次,因为对于其他控制器 post_controller 无法调用钩子。
  • 检查你的Traffic::monitor函数是否因为任何其他原因执行了两次可能是javascript ajaxjavascript redirect。我已经测试了这个钩子,它运行一次而不是两次。
【解决方案2】:

我不熟悉 CodeIgniter,但由于 CI 在路由中支持正则表达式,您可以使用正则表达式 ^\/(?!(admin\b)|login\b\/*|home\b\/*|sign_up\b\/*)[a-zA-Z0-9_\/]*/g 来获取除 /admin /login /home 或 /sign_up 之外的任何内容。 这是一个你可以看看的演示。

说明:

^\/ 匹配 URI 中的起始 /

(?!(admin\b)|login\b\/*|home\b\/*|sign_up\b\/*) 是一切,但不是 admin|login|home|sign_up,这里是 \b "assert position at a word boundary (^\w|\w$|\W\w|\w\W)" 其中表示您可以根据需要使用 adminabc 或 loginxxx 之类的东西,它们会正确匹配。

[a-zA-Z0-9_\/] 这部分是您的 URI 中可接受的字符。

结果:

------Not passing-------
/admin
/login
/admin/xxx
/login/xxx
/home/xxx/login/xxx
/sign_up/xxx/login/xxx
--------passing---------
/
/admintest/xxx
/loginetest/xxx
/hometset/xxx
/sign_uptest/xxx
/others
/others/xxx/login/xxx
/others/xxx/others/xxx/ooo

Demo

希望对你有帮助。

【讨论】:

  • 我出错了。试过 echo preg_match('^\/(?!(admin\b)|login\b\/*|home\b\/*|sign_up\b\/*)[a-zA-Z0-9_\/]* /g', 'asd');
  • @angry_kiwi 我可以通过preg_match('/^\/(?!(admin\b)|login\b\/*|home\b\/*|sign_up\b\/*)[a-zA-Z0-9_\/]*/', '/adminabc', $matches);得到它的工作
  • $match 应该是什么?
  • @angry_kiwi 是匹配结果。如果您不需要它,只需将其删除,preg_match 将返回 0 或 1。请参阅 preg_match 手册php.net/manual/en/function.preg-match.php
  • 奇怪。我试过 echo preg_match('/^\/(?!(admin\b)|login\b\/*|home\b\/*|sign_up\b\/*)[a-zA-Z0-9_\/ ]*/‌​', '管理员');不产生任何结果,没有零也没有 1 个结果
【解决方案3】:

根据 codeigniter documentation,您可以在路由文件中使用正则表达式,因此在这种特殊情况下,通过 knittl 从另一个 SO Answer 中提取:

\b word boundary
\< word start
\> word end

我们可以使用单词边界将您的单词设置为忽略,然后为另一种情况执行相反的正则表达式。

正则表达式获取所有 admin、login、home、signup:

([^\<(admin|login|home|sign_up)\>+-])/g

正则表达式来获取特别是管理员、登录、主页和注册:

([\<(admin|login|home|sign_up)\>+-])

注意使用^ 字符来表示反向关系。

所以最终的路线应该是这样的:

//Typical Route
$route['products/([a-z]+)/(\d+)'] = "$1/id_$2";

//Custom Route to go TO the inverse
$route["base/([^\\<(admin|login|home|sign_up)\\>+-])/"] = "base/$1/";

//Custom Route to go TO admin/login/home/sign_up
$route["base/([\\<(admin|login|home|sign_up)\\>+-])/"] = "base/$1/";

尚未测试,但理论上应该可以。

【讨论】:

  • 它不工作。 echo preg_match("/([^\\+-])/", 'asd');生产 0
最近更新 更多