diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index e20df1c..263280c 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -178,6 +178,7 @@ Yii Framework 2 Change Log - Chg #4201: change default value of `SyslogTarget::facility` from LOG_SYSLOG to LOG_USER (dizews) - Chg #4227: `\yii\widgets\LinkPager::$hideOnSinglePage` is now `true` by default (samdark) - Chg #4318: `yii\helpers\Html::ul()` and `ol()` will return an empty list tag if an empty item array is given (qiangxue) +- Chg #4331: `yii\helpers\Url` now uses `UrlManager` to determine base URL when generating URLs (qiangxue) - Chg: Replaced `clearAll()` and `clearAllAssignments()` in `yii\rbac\ManagerInterface` with `removeAll()`, `removeAllRoles()`, `removeAllPermissions()`, `removeAllRules()` and `removeAllAssignments()` (qiangxue) - Chg: Added `$user` as the first parameter of `yii\rbac\Rule::execute()` (qiangxue) - Chg: `yii\grid\DataColumn::getDataCellValue()` visibility is now `public` to allow accessing the value from a GridView directly (cebe) diff --git a/framework/helpers/BaseUrl.php b/framework/helpers/BaseUrl.php index e31c89d..6e4af54 100644 --- a/framework/helpers/BaseUrl.php +++ b/framework/helpers/BaseUrl.php @@ -196,13 +196,13 @@ class BaseUrl $hasScheme = ($pos = strpos($url, ':')) > 0 && ctype_alpha(substr($url, 0, $pos)); $char = $url[0]; if ($char !== '/' && $char !== '#' && $char !== '.' && !$hasScheme) { - $url = Yii::$app->getRequest()->getBaseUrl() . '/' . $url; + $url = Yii::$app->getUrlManager()->getBaseUrl() . '/' . $url; } } if ($scheme) { if (empty($hasScheme)) { - $url = Yii::$app->getRequest()->getHostInfo() . '/' . ltrim($url, '/'); + $url = Yii::$app->getUrlManager()->getHostInfo() . '/' . ltrim($url, '/'); } if (is_string($scheme) && ($pos = strpos($url, ':')) !== false) { $url = $scheme . substr($url, $pos); @@ -223,9 +223,9 @@ class BaseUrl */ public static function base($scheme = false) { - $url = Yii::$app->getRequest()->getBaseUrl(); + $url = Yii::$app->getUrlManager()->getBaseUrl(); if ($scheme) { - $url = Yii::$app->getRequest()->getHostInfo() . $url; + $url = Yii::$app->getUrlManager()->getHostInfo() . $url; if (is_string($scheme) && ($pos = strpos($url, '://')) !== false) { $url = $scheme . substr($url, $pos); } @@ -306,7 +306,7 @@ class BaseUrl $url = Yii::$app->getHomeUrl(); if ($scheme) { - $url = Yii::$app->getRequest()->getHostInfo() . $url; + $url = Yii::$app->getUrlManager()->getHostInfo() . $url; if (is_string($scheme) && ($pos = strpos($url, '://')) !== false) { $url = $scheme . substr($url, $pos); } diff --git a/framework/web/UrlManager.php b/framework/web/UrlManager.php index cebaddb..3aeb23f 100644 --- a/framework/web/UrlManager.php +++ b/framework/web/UrlManager.php @@ -125,6 +125,7 @@ class UrlManager extends Component public $ruleConfig = ['class' => 'yii\web\UrlRule']; private $_baseUrl; + private $_scriptUrl; private $_hostInfo; /** @@ -298,7 +299,8 @@ class UrlManager extends Component $route = trim($params[0], '/'); unset($params[0]); - $baseUrl = $this->getBaseUrl(); + + $baseUrl = $this->showScriptName || !$this->enablePrettyUrl ? $this->getScriptUrl() : $this->getBaseUrl(); if ($this->enablePrettyUrl) { /* @var $rule UrlRule */ @@ -364,18 +366,18 @@ class UrlManager extends Component } /** - * Returns the base URL that is used by [[createUrl()]] to prepend URLs it creates. - * It defaults to [[Request::scriptUrl]] if [[showScriptName]] is true or [[enablePrettyUrl]] is false; - * otherwise, it defaults to [[Request::baseUrl]]. - * @return string the base URL that is used by [[createUrl()]] to prepend URLs it creates. + * Returns the base URL that is used by [[createUrl()]] to prepend to the URLs it creates. + * It defaults to [[Request::baseUrl]]. + * This is mainly used when [[enablePrettyUrl]] is true and [[showScriptName]] is false. + * @return string the base URL that is used by [[createUrl()]] to prepend to the URLs it creates. * @throws InvalidConfigException if running in console application and [[baseUrl]] is not configured. */ public function getBaseUrl() { if ($this->_baseUrl === null) { $request = Yii::$app->getRequest(); - if ($request instanceof \yii\web\Request) { - $this->_baseUrl = $this->showScriptName || !$this->enablePrettyUrl ? $request->getScriptUrl() : $request->getBaseUrl(); + if ($request instanceof Request) { + $this->_baseUrl = $request->getBaseUrl(); } else { throw new InvalidConfigException('Please configure UrlManager::baseUrl correctly as you are running a console application.'); } @@ -385,7 +387,8 @@ class UrlManager extends Component } /** - * Sets the base URL that is used by [[createUrl()]] to prepend URLs it creates. + * Sets the base URL that is used by [[createUrl()]] to prepend to the URLs it creates. + * This is mainly used when [[enablePrettyUrl]] is true and [[showScriptName]] is false. * @param string $value the base URL that is used by [[createUrl()]] to prepend URLs it creates. */ public function setBaseUrl($value) @@ -394,6 +397,37 @@ class UrlManager extends Component } /** + * Returns the entry script URL that is used by [[createUrl()]] to prepend to the URLs it creates. + * It defaults to [[Request::scriptUrl]]. + * This is mainly used when [[enablePrettyUrl]] is false or [[showScriptName]] is true. + * @return string the entry script URL that is used by [[createUrl()]] to prepend to the URLs it creates. + * @throws InvalidConfigException if running in console application and [[scriptUrl]] is not configured. + */ + public function getScriptUrl() + { + if ($this->_scriptUrl === null) { + $request = Yii::$app->getRequest(); + if ($request instanceof Request) { + $this->_scriptUrl = $request->getScriptUrl(); + } else { + throw new InvalidConfigException('Please configure UrlManager::scriptUrl correctly as you are running a console application.'); + } + } + + return $this->_scriptUrl; + } + + /** + * Sets the entry script URL that is used by [[createUrl()]] to prepend to the URLs it creates. + * This is mainly used when [[enablePrettyUrl]] is false or [[showScriptName]] is true. + * @param string $value the entry script URL that is used by [[createUrl()]] to prepend URLs it creates. + */ + public function setScriptUrl($value) + { + $this->_scriptUrl = $value; + } + + /** * Returns the host info that is used by [[createAbsoluteUrl()]] to prepend URLs it creates. * @return string the host info (e.g. "http://www.example.com") that is used by [[createAbsoluteUrl()]] to prepend URLs it creates. * @throws InvalidConfigException if running in console application and [[hostInfo]] is not configured. diff --git a/tests/unit/framework/helpers/UrlTest.php b/tests/unit/framework/helpers/UrlTest.php index c98227e..d7f0ef4 100644 --- a/tests/unit/framework/helpers/UrlTest.php +++ b/tests/unit/framework/helpers/UrlTest.php @@ -24,6 +24,12 @@ class UrlTest extends TestCase 'hostInfo' => 'http://example.com/', 'url' => '/base/index.php&r=site%2Fcurrent&id=42' ], + 'urlManager' => [ + 'class' => 'yii\web\UrlManager', + 'baseUrl' => '/base', + 'scriptUrl' => '/base/index.php', + 'hostInfo' => 'http://example.com/', + ] ], ], '\yii\web\Application'); } diff --git a/tests/unit/framework/web/UrlManagerTest.php b/tests/unit/framework/web/UrlManagerTest.php index 8d44e28..70e5ccb 100644 --- a/tests/unit/framework/web/UrlManagerTest.php +++ b/tests/unit/framework/web/UrlManagerTest.php @@ -21,6 +21,7 @@ class UrlManagerTest extends TestCase // default setting with '/' as base url $manager = new UrlManager([ 'baseUrl' => '/', + 'scriptUrl' => '', 'cache' => null, ]); $url = $manager->createUrl(['post/view']); @@ -31,6 +32,7 @@ class UrlManagerTest extends TestCase // default setting with '/test/' as base url $manager = new UrlManager([ 'baseUrl' => '/test/', + 'scriptUrl' => '/test', 'cache' => null, ]); $url = $manager->createUrl(['post/view', 'id' => 1, 'title' => 'sample post']); @@ -40,6 +42,7 @@ class UrlManagerTest extends TestCase $manager = new UrlManager([ 'enablePrettyUrl' => true, 'baseUrl' => '/', + 'scriptUrl' => '', 'cache' => null, ]); $url = $manager->createUrl(['post/view', 'id' => 1, 'title' => 'sample post']); @@ -47,13 +50,15 @@ class UrlManagerTest extends TestCase $manager = new UrlManager([ 'enablePrettyUrl' => true, 'baseUrl' => '/test/', + 'scriptUrl' => '/test', 'cache' => null, ]); $url = $manager->createUrl(['post/view', 'id' => 1, 'title' => 'sample post']); $this->assertEquals('/test/post/view?id=1&title=sample+post', $url); $manager = new UrlManager([ 'enablePrettyUrl' => true, - 'baseUrl' => '/test/index.php', + 'baseUrl' => '/test', + 'scriptUrl' => '/test/index.php', 'cache' => null, ]); $url = $manager->createUrl(['post/view', 'id' => 1, 'title' => 'sample post']); @@ -72,6 +77,7 @@ class UrlManagerTest extends TestCase ], ], 'baseUrl' => '/', + 'scriptUrl' => '', ]); $url = $manager->createUrl(['post/view', 'id' => 1, 'title' => 'sample post']); $this->assertEquals('/post/1/sample+post', $url); @@ -89,6 +95,7 @@ class UrlManagerTest extends TestCase ], ], 'baseUrl' => '/', + 'scriptUrl' => '', 'suffix' => '.html', ]); $url = $manager->createUrl(['post/view', 'id' => 1, 'title' => 'sample post']); @@ -108,6 +115,7 @@ class UrlManagerTest extends TestCase ], ], 'baseUrl' => '/test', + 'scriptUrl' => '/test', ]); $url = $manager->createUrl(['post/view', 'id' => 1, 'title' => 'sample post', 'lang' => 'en']); $this->assertEquals('http://en.example.com/test/post/1/sample+post', $url); @@ -119,6 +127,7 @@ class UrlManagerTest extends TestCase { $manager = new UrlManager([ 'baseUrl' => '/', + 'scriptUrl' => '', 'hostInfo' => 'http://www.example.com', 'cache' => null, ]);