Question

I want to load the category name and category url of the item that is displayed as a related item on the productpage.

So inside the foreach element, I want to load the category name and url of the related item itself.

How can I get the category name of a item in Magento 2.3?

I tried the following that seems to work well, but I do not want to a load a objectManager on frontend, so what is the best way to load this otherwise?

<?php $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$product = $objectManager->get('Magento\Framework\Registry')->registry('current_product');
$categories = $product->getCategoryIds(); /*will return category ids array*/
foreach($categories as $category){
    $cat = $objectManager->create('Magento\Catalog\Model\Category')->load($category);
    echo $cat->getName();
    }

?>

HTML:

                                    <?php $items = $block->getProductCollection()->getItems();?>
                <?php foreach ($items as $item) : ?>
                    <?= /* @noEscape */ ($iterator++ == 1) ? '' : '</' . $tag . '>' ?><<?= /* @noEscape */ $tag?> class="product-item">
                    <div class="product">
                        <div class="product-details col-sm-7">
                                <a title="<?= $block->escapeHtml($item->getName()) ?>"
                                   href="<?= $block->escapeUrl($block->getProductUrl($item)) ?>"
                                   class="product-item-link">
                                    <?= $block->escapeHtml($item->getName()) ?>
                                </a>
                            <?= /* @noEscape */ $block->getProductPriceHtml($item, \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE) ?>
                        </div>
                        <div class="product-action col-sm-12">
                            <?php $CatName = $block->getCategoryCollection();
                                echo '<PRE>';print_r($CatName);?>
                        </div>
                    </div>
                <?php endforeach ?>
Was it helpful?

Solution

Create a module and override catalog_product_view.xml in your module. then create one block to set your business logic to the template.

Vendor/Module/view/frontend/layout/catalog_product_view.xml

<?xml version="1.0"?>
<page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="product.info.main">
            <container name="productdetailcat"  htmlTag="div" htmlClass="productdetailcat"  after="product.info.price">
                <block class="Vendor\Module\Block\Custom" name="catnameurl" template="Vendor_Module::custom_cat.phtml" />
            </container>
        </referenceContainer>
    </body>
</page>

Vendor/Module/Block/Custom.php

   <?php 

namespace Vendor\Module\Block;

use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;
use Magento\Framework\View\Page\Config;
use Magento\Framework\Registry;
use Magento\Catalog\Model\CategoryFactory;
use Magento\Catalog\Model\ProductFactory;
use Magento\Catalog\Model\Category;

class Custom extends Template
{
    private $_registry;
    private $_categoryFactory;
    private $_productFactory;
    protected $_category;

    public function __construct(
        Context $context,
        Config $pageConfig,
        Registry $registry,
        Category $catgory,
        CategoryFactory $categoryfactory,
        ProductFactory $productFactory,
        array $data = []
    ) {
        parent::__construct($context, $data);
        $this->pageConfig = $pageConfig;
        $this->_registry = $registry;
        $this->_categoryFactory = $categoryfactory;
        $this->_productFactory = $productFactory;
        $this->_category = $catgory;
    }

    public function getCategoryCollection($productId) 
    {
        $product = $this->_productFactory->create()->load($productId);
        $categories = $product->getCategoryIds();
        foreach($categories as $category)
        {
            $cat = $this->_categoryFactory->create()->load($category);
            $caturl = $cat->getUrl();
            $catName = $cat->getName();
        }

        return $catName;
    }
}

?>

Vendor/Module/view/frontend/templates/custom_cat.phtml

<?php $items = $block->getProductCollection()->getItems();?>
<?php foreach ($items as $item) : ?>
    <?= /* @noEscape */ ($iterator++ == 1) ? '' : '</' . $tag . '>' ?><<?= /* @noEscape */ $tag?> class="product-item">
    <div class="product">
        <div class="product-details col-sm-7">
            <a title="<?= $block->escapeHtml($item->getName()) ?>"
               href="<?= $block->escapeUrl($block->getProductUrl($item)) ?>"
               class="product-item-link">
                <?= $block->escapeHtml($item->getName()) ?>
            </a>
        <?= /* @noEscape */ $block->getProductPriceHtml($item, \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE) ?>
        </div>
        <div class="product-action col-sm-12">
        <?php $CatName = $block->getCategoryCollection($item->getId());
            echo '<PRE>';print_r($CatName);?>
        </div>
    </div>
<?php endforeach ?>

or

use the below code in your template under related foreach. add your block path Vendor\Module\Block\Custom instead of your block name.

$blockObj= $block->getLayout()->createBlock('Vendor\Module\Block\Custom');
$custmcatBlock = $blockObj->getCategoryCollection($item->getId());
echo '<PRE>';print_r($custmcatBlockatName);

Here is display last category name because in foreach return the last name. as per your logic custom in our code and display all cat names and URLs. If You have any query please let me know.

I hope this will help you....!

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top