I try to load categories in the admin area with store specific values.
$this->categoryCollectionFactory->create() ->setStoreId($storeId) ->addAttributeToSelect(['name', 'url_key']);
This works so far, but I don't get the right base URL with
$category->getUrl() if the given store has a different base URL than the admin store.
I checked the
Category::getUrl() method and found out that the store ID is used to determine the correct URL rewrite, but when it's found,
The second argument
getDirectUrl() should receive the scope somehow but it doesn't. So when the base URL is determined, there is no informtion about the current store.
This looks like a bug to me, but is there any way to work around this?
bugfix attempt 1
I traced down the location where the base URL is determined and it's in
return $this->getBaseUrl() . $routeParams['_direct'];
getBaseUrl() takes a
$params argument where the store id can be passed with the
_scope key, but here the argument is empty, so adding
'_scope' => $storeId to the
$params argument in the line from the category model above, would not help either.
bugfix attempt 2
I tried to pass the parameters along to
getBaseUrl() in the line above:
return $this->getBaseUrl($routeParams) . $routeParams['_direct'];
And now getBaseUrl() sets its scope to the given store id:
This loads the correct store model and assigns it to
But to my surprise, a few lines later in
$this->_getScope()->getBaseUrl(), the scope was the admin store again. Why?
_getScope() does not access
$this->_scope ... this is special behavior of
Magento\Backend\Model\Url because there is only one scope for backend URLs.
So here's the next problem: the category should not have been associated with a Backend URL model in the first place. But this apparently happens for any object that receives a
\Magento\Framework\UrlInterface as constructor argument when created in admin area context.
bugfix attempt 3
Magento\Framework\App\State::emulateAreaCode() around the category loading, but still the backend model is used. Found a similar question, Magento 2 get frontend store url for a path in admin, but the recommended solution is to inject a concrete frontend URL instance via preferences or constructor parameter. I don't know if this is a good idea for the core category model.
I tried it anyways, with the following in my module's
<type name="Magento\Catalog\Model\Category"> <arguments> <argument name="url" xsi:type="object">Magento\Framework\Url</argument> </arguments> </type>
And together with the two
core hacks bugfixes from before, I'm getting the correct URLs.
So far, so good. Now I need a real solution :)