Question

I'm trying to get the URL key of any given category with the ID. I have this;

$categoryId = 3;
$_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$object_manager = $_objectManager->create('Magento\Catalog\Model\Category')->load($categoryId);
print_r($object_manager->getData());

And this works (in the print_r there is the URL key I need), but category #3 is the top-level category. Whenever I try any subcategory (say ID 5) I get a blank array. I'm just lost for words, can't figure it out.

In Magento 1.x I used to do this: Mage::getModel('catalog/category')->load($catID)->getUrl() and that worked.

TL;DR: This code works, change the ID to a (correct) category ID and change getData() to getUrl() for the complete category url, or getName() for the category name.

Was it helpful?

Solution

In order to get the category url you need to use the \Magento\Catalog\Model\Category function getUrl() like so:

$category->getUrl()

Also, you can get url by CategoryRepositoryInterface

nameSpace ['Your_nameSpace'] 
use Magento\Catalog\Api\CategoryRepositoryInterface;
class ['Your_Class_name']
    protected $_storeManager;
    protected $categoryRepository;
    public function __construct(
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Catalog\Model\CategoryRepository $categoryRepository,
    ) {
        .........
        $this->_storeManager = $storeManager;
        $this->categoryRepository = $categoryRepository;
    }

     public  function getCategory()
    {
            $category = $this->categoryRepository->get($categoryId, $this->_storeManager->getStore()->getId());

        return $category->getUrl();
    }
} 

OTHER TIPS

Always try to use repository. You need to inject following way:

/**
 * @var \Magento\Catalog\Helper\Category
 */
protected $categoryHelper;

/**
 * @var \Magento\Catalog\Model\CategoryRepository
 */
protected $categoryRepository;


public function __construct(
    \Magento\Catalog\Helper\Category $categoryHelper,
    \Magento\Catalog\Model\CategoryRepository $categoryRepository,

) {
    $this->categoryHelper = $categoryHelper;
    $this->categoryRepository = $categoryRepository;
}

For category url

$categoryId = 3;
$categoryObj = $this->categoryRepository->get($categoryId);
echo  $this->categoryHelper->getCategoryUrl($categoryObj);

You can try below code.

$categoryId = 5;
$_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$object_manager = $_objectManager->create('Magento\Catalog\Model\Category')->load($categoryId);
echo "<pre>";
print_r($object_manager->getData());

Before you use a category id you have confirm category id exists in admin or it will return an empty array.

Let me know if you have any questions.

This works fine on my custom block (using category repository and DI):

/**
 * Constructor
 */
public function __construct(
  \Magento\Catalog\Model\CategoryRepository $categoryRepository,
  // ...
) 
{
  $this->_categoryRepository = $categoryRepository;
  // ...
}


/**
 * Return the category object by its id.
 * 
 * @param categoryId (Integer)
 */
public function getCategory($categoryId)
{
  return $this->getCategoryRepository()->get($categoryId);
}


/**
 * Category repository object
 */
protected $_categoryRepository;

Finally, within a template file I just use:

$this->getCategory(3)->getUrl()

I found that when I need category urls from different domains (per store view), I had to create a new Url object per store view.

use Magento\Catalog\Model\Category;
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory;
use Magento\Framework\UrlFactory;

class CacheWarmer
{
    /** @var CollectionFactory */
    protected $categoryCollectionFactory;

    /** @var \Magento\Store\Model\StoreManagerInterface */
    protected $storeManager;

    /** @var UrlFactory */
    protected $urlFactory;

    public function __construct(
        CollectionFactory $categoryCollectionFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        UrlFactory $urlFactory
    )
    {
        $this->categoryCollectionFactory = $categoryCollectionFactory;
        $this->storeManager = $storeManager;
        $this->urlFactory = $urlFactory;
    }

    /**
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function execute()
    {
        $stores = $this->storeManager->getStores();

        foreach ($stores as $store) {

            $this->storeManager->setCurrentStore($store);

            $collection = $this->categoryCollectionFactory->create();
            $collection->addUrlRewriteToResult();
            $collection->addIsActiveFilter();

            $urlCreator = $this->urlFactory->create();

            /** @var Category $category */
            foreach ($collection as $category) {

                $requestPath = $category->getRequestPath();
                if (!$requestPath) {
                    continue;
                }

                $url = $urlCreator->getDirectUrl($category->getRequestPath());

                $result = @file_get_contents($url);
            }
        }
    }
}

If you care about performance, this is a light Model that you can inject and use.


<?php
declare(strict_types=1);

namespace ModuleNamespace\ModuleName\Model;

use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator;
use Magento\Framework\Phrase;
use Magento\Store\Model\Store;
use Magento\Store\Model\StoreManagerInterface;
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
use Magento\UrlRewrite\Model\UrlFinderInterface;
use Magento\Framework\Exception\NoSuchEntityException;

class GetCategoryUrlByCategoryId
{
    /**
     * @var UrlFinderInterface
     */
    private $urlFinder;

    /**
     * @var StoreManagerInterface
     */
    private $storeManager;

    public function __construct(
        StoreManagerInterface $storeManager,
        UrlFinderInterface $urlFinder
    ) {
        $this->urlFinder = $urlFinder;
        $this->storeManager = $storeManager;
    }

    /**
     * @param string | int $categoryId
     * @param null $storeId
     * @return string
     * @throws NoSuchEntityException
     */
    public function execute($categoryId, $storeId = null): string
    {
        /** @var Store $store */
        $store = $this->storeManager->getStore($storeId);

        /** @var UrlRewrite $rewrite */
        $rewrite = $this->urlFinder->findOneByData(
            [
                UrlRewrite::ENTITY_ID => $categoryId,
                UrlRewrite::ENTITY_TYPE => CategoryUrlRewriteGenerator::ENTITY_TYPE,
                UrlRewrite::STORE_ID => $store->getId(),
            ]
        );

        if (!$rewrite) {
            throw new NoSuchEntityException(new Phrase('Url rewrite does not exist for category ID "%1".', [$categoryId]));
        }

        return $store->getUrl('', ['_direct' => $rewrite->getRequestPath()]);
    }
}

@andrea Please update getCategory method. Either it works well.

/**
 * Return the category object by its id.
 * 
 * @param categoryId (Integer)
 */
public function getCategory($categoryId)
{
  return $this->_categoryRepository->get($categoryId);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top