feature #21755 [Routing] Optimised dumped router matcher, prevent unneeded function calls. (frankdejonge)

This PR was squashed before being merged into the 3.3-dev branch (closes #21755).

Discussion
----------

[Routing] Optimised dumped router matcher, prevent unneeded function calls.

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | none
| License       | MIT
| Doc PR        | does not apply

The application I'm working on is fairly large. Because we had a routing issue (not caused by the framework) I looked through the dumped routing code. I spotted some easy wins. These changes brought down the time for the `match` method to run from ~ 7.5ms to ~2.5ms. It's not a lot, but it's something. I've profiled it several times with blackfire to confirm. The results were very consistent. Mind you, our application has quite a serious amount of routes, a little over 900.

Commits
-------

dd647ffc8a [Routing] Optimised dumped router matcher, prevent unneeded function calls.
This commit is contained in:
Fabien Potencier 2017-02-28 12:11:09 -08:00
commit 9e1b567d62
6 changed files with 278 additions and 70 deletions

View File

@ -105,8 +105,16 @@ EOF;
{
\$allow = array();
\$pathinfo = rawurldecode(\$pathinfo);
\$trimmedPathinfo = rtrim(\$pathinfo, '/');
\$context = \$this->context;
\$request = \$this->request;
\$requestMethod = \$canonicalMethod = \$context->getMethod();
\$scheme = \$context->getScheme();
if ('HEAD' === \$requestMethod) {
\$canonicalMethod = 'GET';
}
$code
@ -133,7 +141,7 @@ EOF;
foreach ($groups as $collection) {
if (null !== $regex = $collection->getAttribute('host_regex')) {
if (!$fetchedHost) {
$code .= " \$host = \$this->context->getHost();\n\n";
$code .= " \$host = \$context->getHost();\n\n";
$fetchedHost = true;
}
@ -217,20 +225,15 @@ EOF;
$hostMatches = false;
$methods = $route->getMethods();
// GET and HEAD are equivalent
if (in_array('GET', $methods) && !in_array('HEAD', $methods)) {
$methods[] = 'HEAD';
}
$supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods));
$regex = $compiledRoute->getRegex();
if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#'.(substr($regex, -1) === 'u' ? 'u' : ''), $regex, $m)) {
if ($supportsTrailingSlash && substr($m['url'], -1) === '/') {
$conditions[] = sprintf("rtrim(\$pathinfo, '/') === %s", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true));
$conditions[] = sprintf('%s === $trimmedPathinfo', var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true));
$hasTrailingSlash = true;
} else {
$conditions[] = sprintf('$pathinfo === %s', var_export(str_replace('\\', '', $m['url']), true));
$conditions[] = sprintf('%s === $pathinfo', var_export(str_replace('\\', '', $m['url']), true));
}
} else {
if ($compiledRoute->getStaticPrefix() && $compiledRoute->getStaticPrefix() !== $parentPrefix) {
@ -263,26 +266,57 @@ EOF;
EOF;
$gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name);
if ($methods) {
if (1 === count($methods)) {
$code .= <<<EOF
if (\$this->context->getMethod() != '$methods[0]') {
if ($methods[0] === 'HEAD') {
$code .= <<<EOF
if ('HEAD' !== \$requestMethod) {
\$allow[] = 'HEAD';
goto $gotoname;
}
EOF;
} else {
$code .= <<<EOF
if ('$methods[0]' !== \$canonicalMethod) {
\$allow[] = '$methods[0]';
goto $gotoname;
}
EOF;
}
} else {
$methods = implode("', '", $methods);
$code .= <<<EOF
if (!in_array(\$this->context->getMethod(), array('$methods'))) {
$methodVariable = 'requestMethod';
if (in_array('GET', $methods)) {
// Since we treat HEAD requests like GET requests we don't need to match it.
$methodVariable = 'canonicalMethod';
$methods = array_filter($methods, function ($method) { return 'HEAD' !== $method; });
}
if (1 === count($methods)) {
$code .= <<<EOF
if ('$methods[0]' !== \$$methodVariable) {
\$allow[] = '$methods[0]';
goto $gotoname;
}
EOF;
} else {
$methods = implode("', '", $methods);
$code .= <<<EOF
if (!in_array(\$$methodVariable, array('$methods'))) {
\$allow = array_merge(\$allow, array('$methods'));
goto $gotoname;
}
EOF;
}
}
}
@ -303,7 +337,7 @@ EOF;
$schemes = str_replace("\n", '', var_export(array_flip($schemes), true));
$code .= <<<EOF
\$requiredSchemes = $schemes;
if (!isset(\$requiredSchemes[\$this->context->getScheme()])) {
if (!isset(\$requiredSchemes[\$scheme])) {
return \$this->redirect(\$pathinfo, '$name', key(\$requiredSchemes));
}

View File

@ -24,8 +24,16 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
{
$allow = array();
$pathinfo = rawurldecode($pathinfo);
$trimmedPathinfo = rtrim($pathinfo, '/');
$context = $this->context;
$request = $this->request;
$requestMethod = $canonicalMethod = $context->getMethod();
$scheme = $context->getScheme();
if ('HEAD' === $requestMethod) {
$canonicalMethod = 'GET';
}
// foo
if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) {
@ -35,8 +43,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
if (0 === strpos($pathinfo, '/bar')) {
// bar
if (preg_match('#^/bar/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) {
$allow = array_merge($allow, array('GET', 'HEAD'));
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_bar;
}
@ -46,8 +54,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
// barhead
if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) {
$allow = array_merge($allow, array('GET', 'HEAD'));
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_barhead;
}
@ -60,17 +68,17 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
if (0 === strpos($pathinfo, '/test')) {
if (0 === strpos($pathinfo, '/test/baz')) {
// baz
if ($pathinfo === '/test/baz') {
if ('/test/baz' === $pathinfo) {
return array('_route' => 'baz');
}
// baz2
if ($pathinfo === '/test/baz.html') {
if ('/test/baz.html' === $pathinfo) {
return array('_route' => 'baz2');
}
// baz3
if ($pathinfo === '/test/baz3/') {
if ('/test/baz3/' === $pathinfo) {
return array('_route' => 'baz3');
}
@ -83,7 +91,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
// baz5
if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) {
if ($this->context->getMethod() != 'POST') {
if ('POST' !== $canonicalMethod) {
$allow[] = 'POST';
goto not_baz5;
}
@ -94,7 +102,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
// baz.baz6
if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) {
if ($this->context->getMethod() != 'PUT') {
if ('PUT' !== $canonicalMethod) {
$allow[] = 'PUT';
goto not_bazbaz6;
}
@ -106,7 +114,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
}
// foofoo
if ($pathinfo === '/foofoo') {
if ('/foofoo' === $pathinfo) {
return array ( 'def' => 'test', '_route' => 'foofoo',);
}
@ -116,7 +124,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
}
// space
if ($pathinfo === '/spa ce') {
if ('/spa ce' === $pathinfo) {
return array('_route' => 'space');
}
@ -161,12 +169,12 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
}
// overridden2
if ($pathinfo === '/multi/new') {
if ('/multi/new' === $pathinfo) {
return array('_route' => 'overridden2');
}
// hey
if ($pathinfo === '/multi/hey/') {
if ('/multi/hey/' === $pathinfo) {
return array('_route' => 'hey');
}
@ -184,7 +192,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
if (0 === strpos($pathinfo, '/aba')) {
// ababa
if ($pathinfo === '/ababa') {
if ('/ababa' === $pathinfo) {
return array('_route' => 'ababa');
}
@ -195,16 +203,16 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
}
$host = $this->context->getHost();
$host = $context->getHost();
if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) {
// route1
if ($pathinfo === '/route1') {
if ('/route1' === $pathinfo) {
return array('_route' => 'route1');
}
// route2
if ($pathinfo === '/c2/route2') {
if ('/c2/route2' === $pathinfo) {
return array('_route' => 'route2');
}
@ -212,7 +220,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
if (preg_match('#^b\\.example\\.com$#si', $host, $hostMatches)) {
// route3
if ($pathinfo === '/c2/route3') {
if ('/c2/route3' === $pathinfo) {
return array('_route' => 'route3');
}
@ -220,7 +228,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) {
// route4
if ($pathinfo === '/route4') {
if ('/route4' === $pathinfo) {
return array('_route' => 'route4');
}
@ -228,26 +236,26 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) {
// route5
if ($pathinfo === '/route5') {
if ('/route5' === $pathinfo) {
return array('_route' => 'route5');
}
}
// route6
if ($pathinfo === '/route6') {
if ('/route6' === $pathinfo) {
return array('_route' => 'route6');
}
if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#si', $host, $hostMatches)) {
if (0 === strpos($pathinfo, '/route1')) {
// route11
if ($pathinfo === '/route11') {
if ('/route11' === $pathinfo) {
return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ());
}
// route12
if ($pathinfo === '/route12') {
if ('/route12' === $pathinfo) {
return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array ( 'var1' => 'val',));
}
@ -280,7 +288,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
}
// route17
if ($pathinfo === '/route17') {
if ('/route17' === $pathinfo) {
return array('_route' => 'route17');
}
@ -288,7 +296,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
if (0 === strpos($pathinfo, '/a')) {
// a
if ($pathinfo === '/a/a...') {
if ('/a/a...' === $pathinfo) {
return array('_route' => 'a');
}

View File

@ -24,8 +24,16 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
{
$allow = array();
$pathinfo = rawurldecode($pathinfo);
$trimmedPathinfo = rtrim($pathinfo, '/');
$context = $this->context;
$request = $this->request;
$requestMethod = $canonicalMethod = $context->getMethod();
$scheme = $context->getScheme();
if ('HEAD' === $requestMethod) {
$canonicalMethod = 'GET';
}
// foo
if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) {
@ -35,8 +43,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
if (0 === strpos($pathinfo, '/bar')) {
// bar
if (preg_match('#^/bar/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) {
$allow = array_merge($allow, array('GET', 'HEAD'));
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_bar;
}
@ -46,8 +54,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
// barhead
if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) {
if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) {
$allow = array_merge($allow, array('GET', 'HEAD'));
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_barhead;
}
@ -60,17 +68,17 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
if (0 === strpos($pathinfo, '/test')) {
if (0 === strpos($pathinfo, '/test/baz')) {
// baz
if ($pathinfo === '/test/baz') {
if ('/test/baz' === $pathinfo) {
return array('_route' => 'baz');
}
// baz2
if ($pathinfo === '/test/baz.html') {
if ('/test/baz.html' === $pathinfo) {
return array('_route' => 'baz2');
}
// baz3
if (rtrim($pathinfo, '/') === '/test/baz3') {
if ('/test/baz3' === $trimmedPathinfo) {
if (substr($pathinfo, -1) !== '/') {
return $this->redirect($pathinfo.'/', 'baz3');
}
@ -91,7 +99,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
// baz5
if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) {
if ($this->context->getMethod() != 'POST') {
if ('POST' !== $canonicalMethod) {
$allow[] = 'POST';
goto not_baz5;
}
@ -102,7 +110,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
// baz.baz6
if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) {
if ($this->context->getMethod() != 'PUT') {
if ('PUT' !== $canonicalMethod) {
$allow[] = 'PUT';
goto not_bazbaz6;
}
@ -114,7 +122,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
}
// foofoo
if ($pathinfo === '/foofoo') {
if ('/foofoo' === $pathinfo) {
return array ( 'def' => 'test', '_route' => 'foofoo',);
}
@ -124,7 +132,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
}
// space
if ($pathinfo === '/spa ce') {
if ('/spa ce' === $pathinfo) {
return array('_route' => 'space');
}
@ -169,12 +177,12 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
}
// overridden2
if ($pathinfo === '/multi/new') {
if ('/multi/new' === $pathinfo) {
return array('_route' => 'overridden2');
}
// hey
if (rtrim($pathinfo, '/') === '/multi/hey') {
if ('/multi/hey' === $trimmedPathinfo) {
if (substr($pathinfo, -1) !== '/') {
return $this->redirect($pathinfo.'/', 'hey');
}
@ -196,7 +204,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
if (0 === strpos($pathinfo, '/aba')) {
// ababa
if ($pathinfo === '/ababa') {
if ('/ababa' === $pathinfo) {
return array('_route' => 'ababa');
}
@ -207,16 +215,16 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
}
$host = $this->context->getHost();
$host = $context->getHost();
if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) {
// route1
if ($pathinfo === '/route1') {
if ('/route1' === $pathinfo) {
return array('_route' => 'route1');
}
// route2
if ($pathinfo === '/c2/route2') {
if ('/c2/route2' === $pathinfo) {
return array('_route' => 'route2');
}
@ -224,7 +232,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
if (preg_match('#^b\\.example\\.com$#si', $host, $hostMatches)) {
// route3
if ($pathinfo === '/c2/route3') {
if ('/c2/route3' === $pathinfo) {
return array('_route' => 'route3');
}
@ -232,7 +240,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) {
// route4
if ($pathinfo === '/route4') {
if ('/route4' === $pathinfo) {
return array('_route' => 'route4');
}
@ -240,26 +248,26 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) {
// route5
if ($pathinfo === '/route5') {
if ('/route5' === $pathinfo) {
return array('_route' => 'route5');
}
}
// route6
if ($pathinfo === '/route6') {
if ('/route6' === $pathinfo) {
return array('_route' => 'route6');
}
if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#si', $host, $hostMatches)) {
if (0 === strpos($pathinfo, '/route1')) {
// route11
if ($pathinfo === '/route11') {
if ('/route11' === $pathinfo) {
return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ());
}
// route12
if ($pathinfo === '/route12') {
if ('/route12' === $pathinfo) {
return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array ( 'var1' => 'val',));
}
@ -292,7 +300,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
}
// route17
if ($pathinfo === '/route17') {
if ('/route17' === $pathinfo) {
return array('_route' => 'route17');
}
@ -300,7 +308,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
if (0 === strpos($pathinfo, '/a')) {
// a
if ($pathinfo === '/a/a...') {
if ('/a/a...' === $pathinfo) {
return array('_route' => 'a');
}
@ -320,9 +328,9 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
}
// secure
if ($pathinfo === '/secure') {
if ('/secure' === $pathinfo) {
$requiredSchemes = array ( 'https' => 0,);
if (!isset($requiredSchemes[$this->context->getScheme()])) {
if (!isset($requiredSchemes[$scheme])) {
return $this->redirect($pathinfo, 'secure', key($requiredSchemes));
}
@ -330,9 +338,9 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
}
// nonsecure
if ($pathinfo === '/nonsecure') {
if ('/nonsecure' === $pathinfo) {
$requiredSchemes = array ( 'http' => 0,);
if (!isset($requiredSchemes[$this->context->getScheme()])) {
if (!isset($requiredSchemes[$scheme])) {
return $this->redirect($pathinfo, 'nonsecure', key($requiredSchemes));
}

View File

@ -24,12 +24,20 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
{
$allow = array();
$pathinfo = rawurldecode($pathinfo);
$trimmedPathinfo = rtrim($pathinfo, '/');
$context = $this->context;
$request = $this->request;
$requestMethod = $canonicalMethod = $context->getMethod();
$scheme = $context->getScheme();
if ('HEAD' === $requestMethod) {
$canonicalMethod = 'GET';
}
if (0 === strpos($pathinfo, '/rootprefix')) {
// static
if ($pathinfo === '/rootprefix/test') {
if ('/rootprefix/test' === $pathinfo) {
return array('_route' => 'static');
}
@ -41,7 +49,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
}
// with-condition
if ($pathinfo === '/with-condition' && ($context->getMethod() == "GET")) {
if ('/with-condition' === $pathinfo && ($context->getMethod() == "GET")) {
return array('_route' => 'with-condition');
}

View File

@ -0,0 +1,101 @@
<?php
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\RequestContext;
/**
* ProjectUrlMatcher.
*
* This class has been auto-generated
* by the Symfony Routing Component.
*/
class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
{
/**
* Constructor.
*/
public function __construct(RequestContext $context)
{
$this->context = $context;
}
public function match($pathinfo)
{
$allow = array();
$pathinfo = rawurldecode($pathinfo);
$trimmedPathinfo = rtrim($pathinfo, '/');
$context = $this->context;
$request = $this->request;
$requestMethod = $canonicalMethod = $context->getMethod();
$scheme = $context->getScheme();
if ('HEAD' === $requestMethod) {
$canonicalMethod = 'GET';
}
// just_head
if ('/just_head' === $pathinfo) {
if ('HEAD' !== $requestMethod) {
$allow[] = 'HEAD';
goto not_just_head;
}
return array('_route' => 'just_head');
}
not_just_head:
// head_and_get
if ('/head_and_get' === $pathinfo) {
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_head_and_get;
}
return array('_route' => 'head_and_get');
}
not_head_and_get:
if (0 === strpos($pathinfo, '/p')) {
// post_and_head
if ('/post_and_get' === $pathinfo) {
if (!in_array($requestMethod, array('POST', 'HEAD'))) {
$allow = array_merge($allow, array('POST', 'HEAD'));
goto not_post_and_head;
}
return array('_route' => 'post_and_head');
}
not_post_and_head:
if (0 === strpos($pathinfo, '/put_and_post')) {
// put_and_post
if ('/put_and_post' === $pathinfo) {
if (!in_array($requestMethod, array('PUT', 'POST'))) {
$allow = array_merge($allow, array('PUT', 'POST'));
goto not_put_and_post;
}
return array('_route' => 'put_and_post');
}
not_put_and_post:
// put_and_get_and_head
if ('/put_and_post' === $pathinfo) {
if (!in_array($canonicalMethod, array('PUT', 'GET'))) {
$allow = array_merge($allow, array('PUT', 'GET'));
goto not_put_and_get_and_head;
}
return array('_route' => 'put_and_get_and_head');
}
not_put_and_get_and_head:
}
}
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
}
}

View File

@ -279,10 +279,59 @@ class PhpMatcherDumperTest extends TestCase
$route->setCondition('context.getMethod() == "GET"');
$rootprefixCollection->add('with-condition', $route);
/* test case 4 */
$headMatchCasesCollection = new RouteCollection();
$headMatchCasesCollection->add('just_head', new Route(
'/just_head',
array(),
array(),
array(),
'',
array(),
array('HEAD')
));
$headMatchCasesCollection->add('head_and_get', new Route(
'/head_and_get',
array(),
array(),
array(),
'',
array(),
array('GET', 'HEAD')
));
$headMatchCasesCollection->add('post_and_head', new Route(
'/post_and_get',
array(),
array(),
array(),
'',
array(),
array('POST', 'HEAD')
));
$headMatchCasesCollection->add('put_and_post', new Route(
'/put_and_post',
array(),
array(),
array(),
'',
array(),
array('PUT', 'POST')
));
$headMatchCasesCollection->add('put_and_get_and_head', new Route(
'/put_and_post',
array(),
array(),
array(),
'',
array(),
array('PUT', 'GET', 'HEAD')
));
return array(
array($collection, 'url_matcher1.php', array()),
array($redirectCollection, 'url_matcher2.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')),
array($rootprefixCollection, 'url_matcher3.php', array()),
array($headMatchCasesCollection, 'url_matcher4.php', array()),
);
}
}