diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 83c13aeafb..dbe63bc3ca 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -59,6 +59,7 @@ Yii Framework 2 Change Log - Enh #9053: Added`yii\grid\RadioButtonColumn` (darwinisgod) - Enh #9162: Added support of closures in `value` for attributes in `yii\widgets\DetailView` (arogachev) - Enh #10896: Select only primary key when counting records in UniqueValidator (developeruz) +- Enh #10970: Allow omit specifying empty default params on URL creation (rob006) - Enh #11037: `yii.js` and `yii.validation.js` use `Regexp.test()` instead of `String.match()` (arogachev, nkovacs) - Enh #11163: Added separate method for client-side validation options `yii\validators\Validator::getClientOptions()` (arogachev) - Enh #11697: Added `filterHaving()`, `andFilterHaving()` and `orFilterHaving()` to `yii\db\Query` (nicdnepr, samdark) diff --git a/framework/web/UrlRule.php b/framework/web/UrlRule.php index 4a193cbe93..ef065bd1bf 100644 --- a/framework/web/UrlRule.php +++ b/framework/web/UrlRule.php @@ -367,8 +367,15 @@ class UrlRule extends Object implements UrlRuleInterface continue; } if (!isset($params[$name])) { - return false; - } elseif (strcmp($params[$name], $value) === 0) { // strcmp will do string conversion automatically + // allow omit empty optional params + // @see https://github.com/yiisoft/yii2/issues/10970 + if (in_array($name, $this->placeholders) && strcmp($value, '') === 0) { + $params[$name] = ''; + } else { + return false; + } + } + if (strcmp($params[$name], $value) === 0) { // strcmp will do string conversion automatically unset($params[$name]); if (isset($this->_paramRules[$name])) { $tr["<$name>"] = ''; diff --git a/tests/framework/web/UrlRuleTest.php b/tests/framework/web/UrlRuleTest.php index f847ff3eb5..eb7b6c45a4 100644 --- a/tests/framework/web/UrlRuleTest.php +++ b/tests/framework/web/UrlRuleTest.php @@ -31,7 +31,7 @@ class UrlRuleTest extends TestCase foreach ($tests as $j => $test) { list ($route, $params, $expected) = $test; $url = $rule->createUrl($manager, $route, $params); - $this->assertEquals($expected, $url, "Test#$i-$j: $name"); + $this->assertSame($expected, $url, "Test#$i-$j: $name"); } } } @@ -483,6 +483,63 @@ class UrlRuleTest extends TestCase ['post/index', ['page' => 2, 'tag' => 'b'], 'post/2-b'], ], ], + [ + 'optional params - example from guide', + [ + 'pattern' => 'posts//', + 'route' => 'post/index', + 'defaults' => ['page' => 1, 'tag' => ''], + ], + [ + ['post/index', ['page' => 1, 'tag' => ''], 'posts'], + ['post/index', ['page' => 2, 'tag' => ''], 'posts/2'], + ['post/index', ['page' => 2, 'tag' => 'news'], 'posts/2/news'], + ['post/index', ['page' => 1, 'tag' => 'news'], 'posts/news'], + // allow skip empty params on URL creation + ['post/index', [], false], + ['post/index', ['tag' => ''], false], + ['post/index', ['page' => 1], 'posts'], + ['post/index', ['page' => 2], 'posts/2'], + ], + ], + [ + 'required params', + [ + 'pattern' => 'about-me', + 'route' => 'site/page', + 'defaults' => ['id' => 1], + ], + [ + ['site/page', ['id' => 1], 'about-me'], + ['site/page', ['id' => 2], false], + ], + ], + [ + 'required default param', + [ + 'pattern' => '', + 'route' => 'site/home', + 'defaults' => ['lang' => 'en'], + ], + [ + ['site/home', ['lang' => 'en'], ''], + ['site/home', ['lang' => ''], false], + ['site/home', [], false], + ], + ], + [ + 'required default empty param', + [ + 'pattern' => '', + 'route' => 'site/home', + 'defaults' => ['lang' => ''], + ], + [ + ['site/home', ['lang' => ''], ''], + ['site/home', ['lang' => 'en'], false], + ['site/home', [], false], + ], + ], [ 'route has parameters', [