Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Filterable Attributes from a category in Magento 2

Tags:

magento2

I have created category "Bag" in Magento 2. having filter attribute:

  1. color
  2. Size

I'm trying to get Filterable Attributes from category "Bag".

I have already done this in Magento 1.9:

Mage::app()->setCurrentStore($store);
$layer = Mage::getModel("catalog/layer");
$category = Mage::getModel("catalog/category")->load($categoryid);  
$layer->setCurrentCategory($category);
$attributes = $layer->getFilterableAttributes();

But it does not seem to work for 2.x

like image 544
Vishal Kamal Avatar asked Dec 19 '16 11:12

Vishal Kamal


People also ask

What are product attributes and categories in Magento 2?

Some of the most elemental tools in managing a Magento 2 store are Product Attributes and Categories. T hey are the two basic methods that Magento 2 provides for differentiating products.

How do I use categories in Magento?

The most basic application of categories is to construct the main navigation menu for your Magento site. In a standard Magento store, the navigation menu is made up of the subcategories assigned to the default root category (with the ID of “2”). In most stores, the sub-subcategories become dropdown menus or “mega menus” of the main categories.

How to add filterable attributes to a category?

Filterable Attributes 1 Step 1: Set up the attribute properties#N#On the Admin sidebar, go to Stores > Attributes > Product.#N#Browse or use... 2 Step 2: Make the category an anchor#N#On the Admin sidebar, go to Catalog > Categories.#N#In the categories tree, select the... 3 Step 3: Test the results More ...

How to remove filterable attribute values with 0 products from layered navigation?

You can use the following steps to remove filterable attribute values with 0 Products from the layered navigation: On the Admin sidebar, go to Stores > Attributes > Product. Browse or use filtered search to find an attribute in the list and open it in edit mode.


1 Answers

I faced the same problem recently.

I documented my investigation here.

I was not able to find framework api to provide filterable attributes for specific category, however I will share workarounds.

Basically all filterable attributes in Magento 2 can be retrived from FilterableAttributeList:

$filterableAttributes = ObjectManager::getInstance()->get(\Magento\Catalog\Model\Layer\Category\FilterableAttributeList::class);
$attributes = $filterableAttributes->getList();

Please use DI instead of ObjectManager::getInstance(). I used it just to have more compact example :)

Retrieving filters involved in layered navigation is a bit more tricky.

$filterableAttributes = ObjectManager::getInstance()->get(\Magento\Catalog\Model\Layer\Category\FilterableAttributeList::class);

$appState = ObjectManager::getInstance()->get(\Magento\Framework\App\State::class);
$layerResolver = ObjectManager::getInstance()->get(\Magento\Catalog\Model\Layer\Resolver::class);
$filterList = ObjectManager::getInstance()->create(
\Magento\Catalog\Model\Layer\FilterList::class,
    [
        'filterableAttributes' => $filterableAttributes
    ]
);

$category = 1234;

$appState->setAreaCode('frontend');
$layer = $layerResolver->get();
$layer->setCurrentCategory($category);
$filters = $filterList->getFilters($layer);

However, this is not the final result. To be sure that filters are actual, it is required to check number of items for each filters. (that check is actually performed during core layered navigation rendering)

$finalFilters = [];
foreach ($filters as $filter) {
    if ($filter->getItemsCount()) {
        $finalFilters[] = $filter;
    }
}

Then you can get filter names and values. ie:

$name = $filter->getName();
foreach ($filter->getItems() as $item) {
    $value = $item->getValue();
}

Finally, I would like to add alternative solution, that is a bit brutal, thought :)

$categoryId = 1234;

$resource = ObjectManager::getInstance()->get(\Magento\Framework\App\ResourceConnection::class);
$connection = $resource->getConnection();

$select = $connection->select()->from(['ea' => $connection->getTableName('eav_attribute')], 'ea.attribute_id')
->join(['eea' => $connection->getTableName('eav_entity_attribute')], 'ea.attribute_id = eea.attribute_id')
->join(['cea' => $connection->getTableName('catalog_eav_attribute')], 'ea.attribute_id = cea.attribute_id')
->join(['cpe' => $connection->getTableName('catalog_product_entity')], 'eea.attribute_set_id = cpe.attribute_set_id')
->join(['ccp' => $connection->getTableName('catalog_category_product')], 'cpe.entity_id = ccp.product_id')
->where('cea.is_filterable = ?', 1)
->where('ccp.category_id = ?', $categoryId)
->group('ea.attribute_id');

$attributeIds = $connection->fetchCol($select);

Then it is possible to use attribute ids to load collection.

 /** @var $collection \Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection */
$collection = $this->collectionFactory->create();
$collection->setItemObjectClass('Magento\Catalog\Model\ResourceModel\Eav\Attribute')
        ->addStoreLabel($this->storeManager->getStore()->getId());
$collection->addFieldToFilter('attribute_id', ['in' => $attributeIds]);
like image 65
Sergii Ivashchenko Avatar answered Oct 12 '22 11:10

Sergii Ivashchenko