19

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.

7 Answers 7

40

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();
    }
} 
3
  • Thank you :) Changing getData to getUrl was the right call.
    – Asitis
    Commented Aug 5, 2016 at 6:08
  • Working fine, Up voted for you Commented Oct 16, 2017 at 11:34
  • please keep in mind that the mehtod getUrl is not defined in the CategoryInterface which is defined as returnValue of the repository's get method. While this will work in most situatons, it is still not guaranteed to do so.
    – Ekk4rd
    Commented Jun 10, 2020 at 7:55
13

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);
1
  • Awesome, thank you. I was attempting to loop through IDs with the CategoryModel which was reloading the same data through iterations. You saved me after a bunch of head scratching! Commented Apr 9, 2018 at 17:32
7

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.

3
  • Uh yeah, that's the exact code I wrote in the OP. But you are correct, I tried on some ID's that I thought existed, but didn't.
    – Asitis
    Commented Aug 5, 2016 at 6:07
  • I'd avoid using the Object manager (Plenty of resources online to suggest why). Also would advise that variables are also named appropriately.
    – Zudian
    Commented Jan 21, 2022 at 17:40
  • Avoid using object manager and direct access to model->load() Commented May 11 at 1:47
4

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()]);
    }
}
1

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);
            }
        }
    }
}
1

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->_categoryRepository->get($categoryId);
}


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

Finally, within a template file I just use:

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

@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);
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.