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
crontabarea - System configuration "Use Web Server Rewrites" is set to "No"
- URL type is
URL_TYPE_LINKorURL_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!