12

I would like get category id by only using category title by using this kind of function.

->load($categoryTitle, 'title')
->getId();

Use case: Get category id by title and put id data to array in migration script.

9 Answers 9

21

You can do it via collections:

First you need to inject a CategoryFactory in your class constructor.

Magento 2.0 & 2.1:

public function __construct(
    ...
    \Magento\Catalog\Model\CategoryFactory $categoryFactory
) {
    $this->_categoryFactory = $categoryFactory;
    parent::__construct(...);
}

Then anywhere else in your class you can do:

$collection = $this->_categoryFactory->create()->getCollection()->addAttributeToFilter('name',$categoryTitle)->setPageSize(1);

if ($collection->getSize()) {
    $categoryId = $collection->getFirstItem()->getId();
}

Magento 2.2:

public function __construct(
    ...
    \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $collecionFactory
) {
    $this->_collectionFactory = $collecionFactory;
    parent::__construct(...);
}

Then anywhere else in your class you can do:

$collection = $this->collecionFactory
                ->create()
                ->addAttributeToFilter('name',$categoryTitle)
                ->setPageSize(1);

if ($collection->getSize()) {
    $categoryId = $collection->getFirstItem()->getId();
}
5
  • Got an error PHP Fatal error: Call to undefined method Magento\Catalog\Model\CategoryFactory::getCollection()
    – kilis
    May 12, 2016 at 13:31
  • 1
    @kilis see my update, you need to use DI to inject that class ;) May 12, 2016 at 13:34
  • For my use case i need this kind of function $collection = $this->_objectManager->create('\Magento\Catalog\Model\CategoryFactory') ->getCollection()->addAttributeToFilter('title',$categoryTitle)->setPageSize(1);
    – kilis
    May 12, 2016 at 13:41
  • 1
    @kilis well it's bad practice to use the object manager directly, you should always use dependency injection May 12, 2016 at 13:42
  • yeah i know. Our project upgrade script is designed like that :/
    – kilis
    May 12, 2016 at 13:43
6

This can be done using service contracts which are considered as best practice.

Edit: The original answer did not show the full paths to the included classes, I had to find the relevant namespaces, so updated the example slightly with a full class and namespaces.

<?php

namespace Vendor\Module\Model\Categories;

use \Magento\Catalog\Api\CategoryListInterface;
use \Magento\Framework\Api\SearchCriteriaInterface;
use \Magento\Framework\Api\Search\FilterGroup;
use \Magento\Framework\Api\FilterBuilder;
use \Magento\Framework\Api\Search\SearchCriteriaBuilder;


class CategoriesFilterSearchService
{
    protected $categoryList;
    /**
     * @var SearchCriteriaBuilder
     */
    protected $searchCriteriaBuilder;

    /**
     * @var FilterBuilder
     */
    protected $filterBuilder;

    public function __construct(
        CategoryListInterface $categoryList,
        SearchCriteriaBuilder $searchCriteriaBuilder,
        FilterBuilder $filterBuilder,
    ) {
        $this->categoryList = $categoryList;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
        $this->filterBuilder         = $filterBuilder;
    }

    public function getNameCategory()
    {
        $enableFilter[] = $this->filterBuilder
            ->setField(\Magento\Catalog\Model\Category::KEY_NAME)
            ->setConditionType('like')
            ->setValue(self::CATEGORY_NAME_HELP) // name of the category on const
            ->create();

        $searchCriteria = $this->searchCriteriaBuilder
            ->addFilters($enableFilter)
            ->create();

        $items = $this->categoryList->getList($searchCriteria)->getItems();

        if (count($items) == 0) {
            return FALSE;
        }

        foreach ($items as $helpCategory) {
            $CategoryId = $helpCategory->getId();
        }
        return $CategoryId;
    }
}
1
  • +1 For best practice part
    – Akif
    Dec 22, 2018 at 22:28
3

You can simple do it using name,

$title = 'womens';
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$collection = $_categoryFactory->create()->getCollection()->addFieldToFilter('name',$title);
echo "<pre>";
print_r($collection->getData());
exit;
2
  • Not for FE use, upgrade script functionality needed.
    – kilis
    May 12, 2016 at 13:53
  • you just have says title, i have updated my answer. May 18, 2016 at 9:16
3

Try Below Code For Phtml File:

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();

$_categoryFactory = $objectManager->get('Magento\Catalog\Model\CategoryFactory');

$categoryTitle = 'Outdoor'; // Category Name

$collection = $_categoryFactory->create()->getCollection()->addFieldToFilter('name', ['in' => $categoryTitle]);

if ($collection->getSize()) {
    $categoryId = $collection->getFirstItem()->getId();
}
1

I got it with help from my collage

$this->_objectManager->get('Magento\Catalog\Model\CategoryFactory')->create()->getCollection()
        ->addFieldToSelect('name')
        ->addFieldToFilter('name', ['in' => $categoryTitle]);

:) Since the collection will only return the record you want you can grab the only result with ->getFirstItem() on the above code

0

To refactor that in a functioning script i suggest using the following

$obj = $bootstrap->getObjectManager();
$_categoryFactory = $obj->get('Magento\Catalog\Model\CategoryFactory');
$collection = $_categoryFactory->create()->getCollection()->addAttributeToFilter('title',$categoryTitle)->setPageSize(1);

if ($collection->getSize()) {
    $categoryId = $collection->getFirstItem()->getCategoryId();
}

Edit: I made and tested a script. I created a file in /scripts/file.php

<?php
use Magento\Framework\App\Bootstrap;
require __DIR__ . '/../app/bootstrap.php';

$bootstrap = Bootstrap::create(BP, $_SERVER);

$obj = $bootstrap->getObjectManager();

// Set the state (not sure if this is neccessary)
$obj = $bootstrap->getObjectManager();
$_categoryFactory = $obj->get('Magento\Catalog\Model\CategoryFactory');
$categoryTitle = 'Test';
$collection = $_categoryFactory->create()->getCollection()->addAttributeToFilter('name',$categoryTitle)->setPageSize(1);
if ($collection->getSize()) {
    $categoryId = $collection->getFirstItem()->getId();
    echo $categoryId; 
}
3
  • Tried your code , but changed first line to $obj = $this->_objectManager; Got an [Magento\Framework\Exception\LocalizedException] Invalid attribute name: title error
    – kilis
    May 12, 2016 at 13:36
  • When you got that error you did not use my script. May 12, 2016 at 14:04
  • I just added a fully tested script. please check that. it will work for sure! May 12, 2016 at 14:09
0

First, you need to inject collection factory class

public function __construct(
    ...
    \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $collecionFactory ) {
    $this->_collectionFactory = $collecionFactory;
    parent::__construct(...); }

After that inside your method, you can do this,

$categoryTitle = 'Men';
$collection = $this->_categoryCollectionFactory->create()->addAttributeToFilter('name',$categoryTitle)->setPageSize(1);

if ($collection->getSize()) {
    $categoryId = $collection->getFirstItem()->getId();
}
0

You can use the method loadByAttribute

/** @var \Magento\Catalog\Model\CategoryFactory $this->_categoryFactory */
$category = $this->_categoryFactory->create()->loadByAttribute('name', $name);
-1

I managed to write my own (more efficient) method:

$entityTypeId = \Magento\Catalog\Setup\CategorySetup::CATEGORY_ENTITY_TYPE_ID;
$row = $this->queryF("SELECT * FROM `eav_attribute` WHERE `entity_type_id` = $entityTypeId AND `attribute_code` = 'name'", 1);
$nameAttributeId = $row['attribute_id'];
$categoryNames = $this->queryF("SELECT * FROM `catalog_category_entity_varchar` WHERE `attribute_id` = '$nameAttributeId'");
$this->categoryNameIdMap = [];
foreach ($categoryNames as $item) {
    $id = $item['entity_id'];
    $title = $item['value'];
    $this->categoryNameIdMap[$title] = $id;
}

This code caches all title:ids into an array, and only query 2 times.

Worked for me. Easier to use!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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