Only sort the keys once per request instead of on each match.

Sorting the keys property by value sorts keys with the same prefix for
free. This does change the order of the keys, but I don't think that is
actually a large issue as it is just a list.

Refs #2991
This commit is contained in:
mark_story 2014-03-10 21:42:26 -04:00
parent 0c207dba4b
commit c0ac61117e
2 changed files with 12 additions and 16 deletions

View file

@ -173,6 +173,10 @@ class CakeRoute {
foreach ($this->keys as $key) { foreach ($this->keys as $key) {
unset($this->defaults[$key]); unset($this->defaults[$key]);
} }
$keys = $this->keys;
sort($keys);
$this->keys = array_reverse($keys);
} }
/** /**
@ -420,7 +424,6 @@ class CakeRoute {
$named = $pass = array(); $named = $pass = array();
foreach ($url as $key => $value) { foreach ($url as $key => $value) {
// keys that exist in the defaults and have different values is a match failure. // keys that exist in the defaults and have different values is a match failure.
$defaultExists = array_key_exists($key, $defaults); $defaultExists = array_key_exists($key, $defaults);
if ($defaultExists && $defaults[$key] != $value) { if ($defaultExists && $defaults[$key] != $value) {
@ -517,16 +520,10 @@ class CakeRoute {
} }
$out = $this->template; $out = $this->template;
if ($this->keys !== array()) { if (!empty($this->keys)) {
$search = $replace = array(); $search = $replace = array();
$lengths = array_map('strlen', $this->keys); foreach ($this->keys as $key) {
$flipped = array_combine($this->keys, $lengths);
arsort($flipped);
$keys = array_keys($flipped);
foreach ($keys as $key) {
$string = null; $string = null;
if (isset($params[$key])) { if (isset($params[$key])) {
$string = $params[$key]; $string = $params[$key];
@ -537,7 +534,6 @@ class CakeRoute {
$replace[] = $string; $replace[] = $string;
} }
$out = str_replace($search, $replace, $out); $out = str_replace($search, $replace, $out);
} }
if (strpos($this->template, '*')) { if (strpos($this->template, '*')) {

View file

@ -118,7 +118,7 @@ class CakeRouteTest extends CakeTestCase {
$this->assertRegExp($result, '/posts/view/518098'); $this->assertRegExp($result, '/posts/view/518098');
$this->assertNotRegExp($result, '/posts/edit/name-of-post'); $this->assertNotRegExp($result, '/posts/edit/name-of-post');
$this->assertNotRegExp($result, '/posts/edit/4/other:param'); $this->assertNotRegExp($result, '/posts/edit/4/other:param');
$this->assertEquals(array('controller', 'action', 'id'), $route->keys); $this->assertEquals(array('id', 'controller', 'action'), $route->keys);
$route = new CakeRoute( $route = new CakeRoute(
'/:lang/:controller/:action/:id', '/:lang/:controller/:action/:id',
@ -130,7 +130,7 @@ class CakeRouteTest extends CakeTestCase {
$this->assertRegExp($result, '/cze/articles/view/1'); $this->assertRegExp($result, '/cze/articles/view/1');
$this->assertNotRegExp($result, '/language/articles/view/2'); $this->assertNotRegExp($result, '/language/articles/view/2');
$this->assertNotRegExp($result, '/eng/articles/view/name-of-article'); $this->assertNotRegExp($result, '/eng/articles/view/name-of-article');
$this->assertEquals(array('lang', 'controller', 'action', 'id'), $route->keys); $this->assertEquals(array('lang', 'id', 'controller', 'action'), $route->keys);
foreach (array(':', '@', ';', '$', '-') as $delim) { foreach (array(':', '@', ';', '$', '-') as $delim) {
$route = new CakeRoute('/posts/:id' . $delim . ':title'); $route = new CakeRoute('/posts/:id' . $delim . ':title');
@ -141,7 +141,7 @@ class CakeRouteTest extends CakeTestCase {
$this->assertNotRegExp($result, '/posts/11!nameofarticle'); $this->assertNotRegExp($result, '/posts/11!nameofarticle');
$this->assertNotRegExp($result, '/posts/11'); $this->assertNotRegExp($result, '/posts/11');
$this->assertEquals(array('id', 'title'), $route->keys); $this->assertEquals(array('title', 'id'), $route->keys);
} }
$route = new CakeRoute( $route = new CakeRoute(
@ -155,7 +155,7 @@ class CakeRouteTest extends CakeTestCase {
$this->assertNotRegExp($result, '/posts/hey_now:nameofarticle'); $this->assertNotRegExp($result, '/posts/hey_now:nameofarticle');
$this->assertNotRegExp($result, '/posts/:nameofarticle/2009'); $this->assertNotRegExp($result, '/posts/:nameofarticle/2009');
$this->assertNotRegExp($result, '/posts/:nameofarticle/01'); $this->assertNotRegExp($result, '/posts/:nameofarticle/01');
$this->assertEquals(array('id', 'title', 'year'), $route->keys); $this->assertEquals(array('year', 'title', 'id'), $route->keys);
$route = new CakeRoute( $route = new CakeRoute(
'/posts/:url_title-(uuid::id)', '/posts/:url_title-(uuid::id)',
@ -204,7 +204,7 @@ class CakeRouteTest extends CakeTestCase {
$this->assertRegExp($result, '/some_extra/page/this_is_the_slug'); $this->assertRegExp($result, '/some_extra/page/this_is_the_slug');
$this->assertRegExp($result, '/page/this_is_the_slug'); $this->assertRegExp($result, '/page/this_is_the_slug');
$this->assertEquals(array('extra', 'slug'), $route->keys); $this->assertEquals(array('slug', 'extra'), $route->keys);
$this->assertEquals(array('extra' => '[a-z1-9_]*', 'slug' => '[a-z1-9_]+', 'action' => 'view'), $route->options); $this->assertEquals(array('extra' => '[a-z1-9_]*', 'slug' => '[a-z1-9_]+', 'action' => 'view'), $route->options);
$expected = array( $expected = array(
'controller' => 'pages', 'controller' => 'pages',
@ -864,8 +864,8 @@ class CakeRouteTest extends CakeTestCase {
$route = new CakeRoute('/:thisParam/:thisParamIsLonger'); $route = new CakeRoute('/:thisParam/:thisParamIsLonger');
$url = array( $url = array(
'thisParamIsLonger' => 'bar',
'thisParam' => 'foo', 'thisParam' => 'foo',
'thisParamIsLonger' => 'bar'
); );
$result = $route->match($url); $result = $route->match($url);