How to display the category image in the topmenu?
I need to edit/overwrite the block file, but I can't get the code to actually extract the image.
Magento Stack Exchange is a question and answer site for users of the Magento e-Commerce platform. It only takes a minute to sign up.
Sign up to join this communityHow to display the category image in the topmenu?
I need to edit/overwrite the block file, but I can't get the code to actually extract the image.
Look at
vendor/magento/module-catalog/etc/di.xml
<type name="Magento\Theme\Block\Html\Topmenu">
<plugin name="catalogTopmenu" type="Magento\Catalog\Plugin\Block\Topmenu" />
</type>
As we can see, Magento uses Plugin - Magento\Catalog\Plugin\Block\Topmenu
to override some methods of Magento\Theme\Block\Html\Topmenu
class. We should see more vendor/magento/module-catalog/Plugin/Block/Topmenu.php.
We can disable the default plugin in your module and re-build your own Plugin which follow the logic of Magento\Catalog\Plugin\Block\Topmenu
class.
Vendor\Module\etc\di.xml
<type name="Magento\Theme\Block\Html\Topmenu">
<plugin name="catalogTopmenu" disabled="true" />
<plugin name="catalogTopmenuImage" type="Vendor\Module\Plugin\Block\Topmenu" />
</type>
From my understanding, we should to rebuild some methods:
vendor/magento/module-catalog/Plugin/Block/Topmenu.php
...
/**
* Convert category to array
*
* @param \Magento\Catalog\Model\Category $category
* @param \Magento\Catalog\Model\Category $currentCategory
* @return array
*/
private function getCategoryAsArray($category, $currentCategory)
{
return [
'name' => $category->getName(),
'id' => 'category-node-' . $category->getId(),
'url' => $this->catalogCategory->getCategoryUrl($category),
'has_active' => in_array((string)$category->getId(), explode('/', $currentCategory->getPath()), true),
'is_active' => $category->getId() == $currentCategory->getId(),
'image_url' => $category->getImageUrl(), // Get image URL
];
}
/**
* Get Category Tree
*
* @param int $storeId
* @param int $rootId
* @return \Magento\Catalog\Model\ResourceModel\Category\Collection
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function getCategoryTree($storeId, $rootId)
{
/** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
$collection = $this->collectionFactory->create();
$collection->setStoreId($storeId);
$collection->addAttributeToSelect('name');
$collection->addAttributeToSelect('image'); // Select image
$collection->addFieldToFilter('path', ['like' => '1/' . $rootId . '/%']); //load only from store root
$collection->addAttributeToFilter('include_in_menu', 1);
$collection->addIsActiveFilter();
$collection->addUrlRewriteToResult();
$collection->addOrder('level', Collection::SORT_ORDER_ASC);
$collection->addOrder('position', Collection::SORT_ORDER_ASC);
$collection->addOrder('parent_id', Collection::SORT_ORDER_ASC);
$collection->addOrder('entity_id', Collection::SORT_ORDER_ASC);
return $collection;
}
...
You can then use $child->getDataByKey('image_url')
in Topmenu::_getHtml()
(via an extending module, as explained here). For example, the below will replace the category name with the image (if there is one):
protected function _getHtml(
\Magento\Framework\Data\Tree\Node $menuTree,
$childrenWrapClass,
$limit,
$colBrakes = []
) {
$html = '';
$children = $menuTree->getChildren();
$parentLevel = $menuTree->getLevel();
$childLevel = $parentLevel === null ? 0 : $parentLevel + 1;
$counter = 1;
$itemPosition = 1;
$childrenCount = $children->count();
$parentPositionClass = $menuTree->getPositionClass();
$itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';
foreach ($children as $child) {
$child->setLevel($childLevel);
$child->setIsFirst($counter == 1);
$child->setIsLast($counter == $childrenCount);
$child->setPositionClass($itemPositionClassPrefix . $counter);
$outermostClassCode = '';
$outermostClass = $menuTree->getOutermostClass();
if ($childLevel == 0 && $outermostClass) {
$outermostClassCode = ' class="' . $outermostClass . '" ';
$child->setClass($outermostClass);
}
if (count($colBrakes) && $colBrakes[$counter]['colbrake']) {
$html .= '</ul></li><li class="column"><ul>';
}
$html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>';
$html .= '<a href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>';
// Use category image instead of name if available
$html .= $child->getDataByKey('image_url') ? '<img src="' . $child->getDataByKey('image_url') . '">' : $this->escapeHtml($child->getName());
$html .= '</span></a>' . $this->_addSubMenu(
$child,
$childLevel,
$childrenWrapClass,
$limit
) . '</li>';
$itemPosition++;
$counter++;
}
if (count($colBrakes) && $limit) {
$html = '<li class="column"><ul>' . $html . '</ul></li>';
}
return $html;
}
Magento\Catalog\Plugin\Block\Topmenu
class.
– Khoa TruongDinh
Aug 16 '16 at 13:31
vendor/magento/module-catalog/Plugin/Block
. In vendor/magento/module-catalog/Plugin
, I just got Model
– Memes
Aug 17 '16 at 1:59
vendor/magento/module-catalog/Plugin/Block/Topmenu.php
. Please check again.
– Khoa TruongDinh
Aug 17 '16 at 2:25