@@ -118,18 +118,39 @@ public function addExpressionLanguageProvider(ExpressionFunctionProviderInterfac
118
118
*/
119
119 protected function matchCollection ($ pathinfo , RouteCollection $ routes )
120
120
{
121
+ $ supportsTrailingSlash = '/ ' !== $ pathinfo && '' !== $ pathinfo && $ this instanceof RedirectableUrlMatcherInterface;
122
+
121
123
foreach ($ routes as $ name => $ route ) {
122
124
$ compiledRoute = $ route ->compile ();
125
+ $ staticPrefix = $ compiledRoute ->getStaticPrefix ();
123
126
124
127
// check the static prefix of the URL first. Only use the more expensive preg_match when it matches
125
- if ('' !== $ compiledRoute ->getStaticPrefix () && 0 !== strpos ($ pathinfo , $ compiledRoute ->getStaticPrefix ())) {
128
+ if ('' === $ staticPrefix || 0 === strpos ($ pathinfo , $ staticPrefix )) {
129
+ // no-op
130
+ } elseif (!$ supportsTrailingSlash ) {
131
+ continue ;
132
+ } elseif ('/ ' === substr ($ staticPrefix , -1 ) && substr ($ staticPrefix , 0 , -1 ) === $ pathinfo ) {
133
+ return ;
134
+ } else {
126
135
continue ;
127
136
}
137
+ $ regex = $ compiledRoute ->getRegex ();
138
+
139
+ if ($ supportsTrailingSlash && $ pos = strpos ($ regex , '/$ ' )) {
140
+ $ regex = substr ($ regex , 0 , $ pos ).'/?$ ' .substr ($ regex , $ pos + 2 );
141
+ $ hasTrailingSlash = true ;
142
+ } else {
143
+ $ hasTrailingSlash = false ;
144
+ }
128
145
129
- if (!preg_match ($ compiledRoute -> getRegex () , $ pathinfo , $ matches )) {
146
+ if (!preg_match ($ regex , $ pathinfo , $ matches )) {
130
147
continue ;
131
148
}
132
149
150
+ if ($ hasTrailingSlash && '/ ' !== substr ($ pathinfo , -1 )) {
151
+ return ;
152
+ }
153
+
133
154
$ hostMatches = array ();
134
155
if ($ compiledRoute ->getHostRegex () && !preg_match ($ compiledRoute ->getHostRegex (), $ this ->context ->getHost (), $ hostMatches )) {
135
156
continue ;
0 commit comments