使用正则表达式一致地匹配路由


Match route consistently with regex

我正在创建一个简单的路由系统供个人使用。添加路线像这样的东西:

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中有可选的标题,如果"edit"或"delete"在实际url中没有尾部斜杠,我的系统调用show()编辑()或删除(),具体取决于url。因此,如果url有"编辑"或"删除",无论它是否包含尾部斜杠,它应该只触发该方法,而不是show(),后者应该只有当url包含类似"/news/"或"/news"的内容时才调用。

为了进一步澄清,如果我有类似"/news/17/delete"(没有拖尾/)的url调用show()和delete()。但是,如果url看起来像"/news/17/delete/"(带有尾随斜杠),则不调用show(),wich是正确的。

这是Router类,如果它有帮助的话(如果我把它粘贴在这里,请告诉我)。https://github.com/FernandoBasso/phprouter/blob/master/helpers/class.Router.php

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

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

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路由。

你有没有尝试过这样的东西:

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/