diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index f521c80e76..3a03a16965 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -21,6 +21,7 @@ Yii Framework 2 Change Log - Bug #18325: Fix `yii\db\pgsql\Schema` to respect non-default PgSQL schema name for data types (theonedemon, silverfire) - Bug #18593: Fix setting the `maxlength` attribute for `Html::activeInput()` and `Html::activeTextArea()` based on `length` parameter of validator (BSCheshir) - Bug #18592: Fix `yii\db\Command::getRawSql()` to not replace query params in invalid places (sartor) +- Bug #18590: Fix `yii\web\UrlManager` to instantiate cache only when it's actually needed (bizley) 2.0.41.1 March 04, 2021 ----------------------- diff --git a/framework/web/UrlManager.php b/framework/web/UrlManager.php index 13e15e4d20..92c73d3fe9 100644 --- a/framework/web/UrlManager.php +++ b/framework/web/UrlManager.php @@ -119,7 +119,7 @@ class UrlManager extends Component */ public $routeParam = 'r'; /** - * @var CacheInterface|array|string the cache object or the application component ID of the cache object. + * @var CacheInterface|array|string|bool the cache object or the application component ID of the cache object. * This can also be an array that is used to create a [[CacheInterface]] instance in case you do not want to use * an application component. * Compiled URL rules will be cached through this cache object, if it is available. @@ -185,17 +185,10 @@ class UrlManager extends Component if (!$this->enablePrettyUrl) { return; } - if ($this->cache !== false && $this->cache !== null) { - try { - $this->cache = Instance::ensure($this->cache, 'yii\caching\CacheInterface'); - } catch (InvalidConfigException $e) { - Yii::warning('Unable to use cache for URL manager: ' . $e->getMessage()); - } + + if (!empty($this->rules)) { + $this->rules = $this->buildRules($this->rules); } - if (empty($this->rules)) { - return; - } - $this->rules = $this->buildRules($this->rules); } /** @@ -263,6 +256,23 @@ class UrlManager extends Component return $builtRules; } + /** + * @return CacheInterface|null|bool + */ + private function ensureCache() + { + if (!$this->cache instanceof CacheInterface && $this->cache !== false && $this->cache !== null) { + try { + $this->cache = Instance::ensure($this->cache, 'yii\caching\CacheInterface'); + } catch (InvalidConfigException $e) { + Yii::warning('Unable to use cache for URL manager: ' . $e->getMessage()); + $this->cache = null; + } + } + + return $this->cache; + } + /** * Stores $builtRules to cache, using $rulesDeclaration as a part of cache key. * @@ -274,11 +284,12 @@ class UrlManager extends Component */ protected function setBuiltRulesCache($ruleDeclarations, $builtRules) { - if (!$this->cache instanceof CacheInterface) { + $cache = $this->ensureCache(); + if (!$cache) { return false; } - return $this->cache->set([$this->cacheKey, $this->ruleConfig, $ruleDeclarations], $builtRules); + return $cache->set([$this->cacheKey, $this->ruleConfig, $ruleDeclarations], $builtRules); } /** @@ -292,11 +303,12 @@ class UrlManager extends Component */ protected function getBuiltRulesFromCache($ruleDeclarations) { - if (!$this->cache instanceof CacheInterface) { + $cache = $this->ensureCache(); + if (!$cache) { return false; } - return $this->cache->get([$this->cacheKey, $this->ruleConfig, $ruleDeclarations]); + return $cache->get([$this->cacheKey, $this->ruleConfig, $ruleDeclarations]); } /** diff --git a/tests/framework/web/UrlManagerCreateUrlTest.php b/tests/framework/web/UrlManagerCreateUrlTest.php index ae95c2a855..a2f894c24b 100644 --- a/tests/framework/web/UrlManagerCreateUrlTest.php +++ b/tests/framework/web/UrlManagerCreateUrlTest.php @@ -837,4 +837,25 @@ class UrlManagerCreateUrlTest extends TestCase $this->assertInstanceOf(UrlRule::className(), $urlManager->rules[0]); $this->assertInstanceOf(CachedUrlRule::className(), $cachedUrlManager->rules[0]); } + + public function testNotEnsuringCacheForEmptyRuleset() + { + $this->mockWebApplication([ + 'components' => [ + 'cache' => ArrayCache::className(), + ], + ]); + // no rules - don't ensure cache + $urlManager = $this->getUrlManager([ + 'cache' => 'cache', + 'rules' => [], + ]); + $this->assertSame('cache', $urlManager->cache); + // with rules - ensure cache + $urlManager = $this->getUrlManager([ + 'cache' => 'cache', + 'rules' => ['/' => 'site/index'], + ]); + $this->assertInstanceOf(ArrayCache::className(), $urlManager->cache); + } }