Local Storage seems to be disabled in your browser.
For the best experience on our site, be sure to turn on Local Storage in your browser.
`magento` appears in URL when "Use Web Server Rewrites" set to "No" and in CLI environment

In an internal test case, we found a strange behavior that when trying to build URL in custom CLI commands, the URL sometimes contains an unexpected magento
in its URI part. In this blog, let's examine why this happens and how to workaround it.
Behavior
Run the following code in CLI environment.
/** @var \Magento\Store\Api\Data\StoreInterface $store */
echo $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_LINK) . "\n";
Sometimes, you will get the output like http://example.com/magento/
.
However, the expected output is http://example.com/
or http://example.com/index.php/
.
So where does the magento
come from?
The Cause
This is due to a bug in \Magento\Store\Model\Store::_updatePathUseRewrites method.
/**
* Append script file name to url in case when server rewrites are disabled
*
* @param string $url
* @return string
*/
protected function _updatePathUseRewrites($url)
{
if ($this->getForceDisableRewrites() || !$this->getConfig(self::XML_PATH_USE_REWRITES)) {
if ($this->_isCustomEntryPoint()) {
$indexFileName = 'index.php';
} else {
$scriptFilename = $this->_request->getServer('SCRIPT_FILENAME');
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$indexFileName = is_string($scriptFilename) ? basename($scriptFilename) : '';
}
$url .= $indexFileName . '/';
}
return $url;
}
Note this line:
$indexFileName = is_string($scriptFilename) ? basename($scriptFilename) : '';
In CLI environment, $scriptFilename
is bin/magento
, so basename($scriptFilename)
becomes magento
.
That's where the magento
comes from.
Conditions
By analyzing the above code, we can also figure out the conditions that can trigger this bug.
- CLI but not in
crontab
area - System configuration "Use Web Server Rewrites" is set to "No"
- URL type is
URL_TYPE_LINK
orURL_TYPE_DIRECT_LINK
Cron is unaffected, why?
However, the getBaseUrl
method works correctly in crontab
area.
The reason is that during the Object Manager
initialization in crontab
area, its "custom entry parameter" is set to true
.
(\Magento\Cron\Console\Command\CronCommand#L122)
$omParams[Store::CUSTOM_ENTRY_POINT_PARAM] = true;
Then this initialization parameter is injected to \Magento\Store\Model\Store
.
(vendor/magento/module-store/etc/di.xml#L98)
<type name="Magento\Store\Model\Store">
<arguments>
<argument name="session" xsi:type="object" shared="false">Magento\Framework\Session\Generic\Proxy</argument>
<argument name="isCustomEntryPoint" xsi:type="init_parameter">Magento\Store\Model\Store::CUSTOM_ENTRY_POINT_PARAM</argument>
<argument name="url" xsi:type="object" shared="false">Magento\Framework\UrlInterface</argument>
</arguments>
</type>
Workaround
Now, we know the conditions that can trigger the bug, the workaround is pretty straightforward.
This workaround does not add extra dependencies.
$type = \Magento\Framework\UrlInterface::URL_TYPE_LINK;
/** @var \Magento\Store\Api\Data\StoreInterface $store */
$baseUrl = $store->getBaseUrl($type);
echo $baseUrl . "\n";
if ((PHP_SAPI === 'cli')
&&
($store->getForceDisableRewrites()
|| !$store->getConfig(\Magento\Store\Model\Store::XML_PATH_USE_REWRITES))
&&
($type === UrlInterface::URL_TYPE_LINK || $type === UrlInterface::URL_TYPE_DIRECT_LINK)
&&
// phpcs:ignore Magento2.Security.Superglobal.SuperglobalUsageWarning
(isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] === 'bin/magento')
) {
$baseUrl = preg_replace(
'|^(?i)(https?)(?-i)://([^/\?#]*)/magento/(.*)$|u',
'${1}://${2}/index.php/${3}',
$baseUrl
);
}
echo $baseUrl . "\n";
Output
http://example.com/magento/
http://example.com/index.php/
Related Issues
- Bug when "Use Web Server Rewrites" is set to "No".
https://github.com/magento/magento2/issues/25976 - As we confirmed, this bug is still not fixed on this blog post date.
- This bug may not be obvious due to the fact that most production environments set "Use Web Server Rewrites" to "Yes".
If you found this blog post helpful, please share it!