Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/240.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 将路由与正则表达式一致地匹配_Php_Regex_Router - Fatal编程技术网

Php 将路由与正则表达式一致地匹配

Php 将路由与正则表达式一致地匹配,php,regex,router,Php,Regex,Router,我正在为个人使用创建一个简单的路由系统。添加路由将继续 大概是这样的: Router::add('/news/?', [ 'controller' => 'NewsController', 'method' => 'index' ]); // /news/17, /news/17/, /news/17/a-title-here Router::add('/news/\d+/?[^/]*', [ 'controller' => 'NewsController', 'method'

我正在为个人使用创建一个简单的路由系统。添加路由将继续 大概是这样的:

Router::add('/news/?', [ 'controller' => 'NewsController', 'method' => 'index' ]);
// /news/17, /news/17/, /news/17/a-title-here
Router::add('/news/\d+/?[^/]*', [ 'controller' => 'NewsController', 'method' => 'show' ]);
Router::add('/news/\d+/edit/?', [ 'controller' => 'NewsController', 'method' => 'edit' ]);
Router::add('/news/\d+/delete/?', [ 'controller' => 'NewsController', 'method' => 'delete' ]);
问题是,因为第二条规则允许url中有可选标题, 如果“编辑”或“删除”在实际url中没有尾随斜杠, 我的系统调用show()edit()或delete(),具体取决于系统中的内容 url。因此,如果url有“编辑”或“删除”,无论它是否包含 尾随斜杠,它应该只触发该方法,而不是show(),它应该 仅当url包含“/news/”或“/news”之类的内容时才能调用

再澄清一点,如果我有像“/news/17/delete”(no trailing/)这样的url,它 调用show()和delete()。但是,如果url看起来像“/news/17/delete/”,则带有 尾随斜杠),则不调用show(),这是正确的

这是Router类,以防有帮助(如果我要粘贴在这里,请告诉我)。


编辑:感谢所有帮助过我的人。我从你分享的所有想法中学到了很多,如果可能的话,我会接受它们作为答案。:)

您是否尝试过类似的方法:

Router::add('/news/\d+/?(?!/?(?:edit|delete))[^/]*$', [ 'controller' => 'NewsController', 'method' => 'show' ]);

排除第二条规则与编辑或删除规则匹配的可能性:

Router::add('/news/\d+/?(?!edit/?$|delete/?$)[^/]*', [ 'controller' => 'NewsController', 'method' => 'show' ]);
这应该是可行的,因为它将允许通过以下示例:

/news/12/foo
/news/12/foo-delete
/news/12/delete-foo
但不是:

/news/12/delete
/news/12/delete/
/news/12/edit
/news/12/edit/

您应该按顺序处理路线,从最具体到最通用,并在找到匹配项后立即停止,例如:

Router::add('/news/\d+/edit/?', [ 'controller' => 'NewsController', 'method' => 'edit' ]);
Router::add('/news/\d+/delete/?', [ 'controller' => 'NewsController', 'method' => 'delete' ]);
Router::add('/news/\d+/?[^/]*', [ 'controller' => 'NewsController', 'method' => 'show' ]);
Router::add('/news/?', [ 'controller' => 'NewsController', 'method' => 'index' ]);

这样,当您循环遍历它们时,您尝试首先匹配
/news/:id/:action
路由。

您应该按顺序处理路由,从最特定到最通用,并在找到匹配项后立即停止。为什么要如此灵活地允许调用方自行决定是否包含尾随斜杠?为什么不对此采取单一方法?您是否考虑过实际使用HTTP动词(GET、POST、PUT、DELETE)来确定操作而不是URI段?这是我的第一个选择。但我并没有完全无视它。我还没有决定是否应该采取单一的办法。它有优点也有缺点。我觉得奇怪的是,url会因为缺少或额外的“/”而导致“资源”加载失败。我会重新考虑的。谢谢。@moonwave99,你的建议奏效了。实际上,我在循环中有一个带注释的“break”语句来查找匹配项。只需将“编辑”和“删除”路由放在“列表”和“显示”路由之上,就可以了。很有道理。如果你回答了这个问题,我会接受它。@MikeBrant,但是我如何才能从用于编辑资源的表单发送PUT动词(例如)?我考虑过,但放弃了它,因为“edit”和“delete”可能出现在标题中。我错过了一些明显的东西吗?基于Ed Cottrell的代码和你的,我会考虑这个方法。是的,标题不太可能包含一个单独的编辑或删除单词。我会考虑一下。如果是这样的话,它将与您的协议冲突——您将如何触发对标题为“delete”的项目的编辑或删除?换句话说,你不应该允许一个项目有标题“编辑”或“删除”。我明白了。这是有道理的。如果您真的想要标题为“编辑”或“删除”的项目,请调整协议,使仅查看请求看起来像
/news/\d+/view/*
(或类似)-这将消除任何歧义。