I have a custom product attribute brands
, this is a dropdown option that has dynamic select value, basically i want to add a custom layer navigation filter to check whether the product attribute value is filled or not, I tried to create a custom filter for layered navigation like this:
app/code/Vendor/Module/etc/di.xml
<type name="Magento\Catalog\Model\Layer\FilterList">
<plugin disabled="false" name="custom_filter_plugin" sortOrder="10" type="Vendor\Module\Plugin\Magento\Catalog\Model\Layer\FilterList"/>
</type>
app/code/Vendor/Module/Plugin/Magento/Catalog/Model/Layer/FilterList.php
class FilterList
{
const IS_BRANDS_FILTER_CLASS = '\Vendor\Module\Model\Layer\Filter\IsBrands';
public function __construct(
\Magento\Framework\ObjectManagerInterface $objectManager
) {
$this->_objectManager = $objectManager;
}
public function beforeGetFilters(
\Magento\Catalog\Model\Layer\FilterList $subject,
$layer
) {
//Your plugin code
$layer->getProductCollection()->addAttributeToSelect('brands');
return [$layer];
}
public function afterGetFilters(
\Magento\Catalog\Model\Layer\FilterList $subject,
$result,
$layer
) {
$result[] = $this->_objectManager->create(
self::IS_BRANDS_FILTER_CLASS,
['layer' => $layer]
);
return $result;
}
}
app/code/Vendor/Module/Model/Layer/Filter/IsBrands.php
class IsBrands extends \Magento\Catalog\Model\Layer\Filter\AbstractFilter
{
const FILTER_IS_BRANDS = 1;
const FILTER_IS_NOT_BRANDS = 2;
protected $_activeFilter = false;
protected $_requestVar = 'is_brands';
/**
* @param \Magento\Catalog\Model\Layer\Filter\ItemFactory $filterItemFactory
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Catalog\Model\Layer $layer
* @param \Magento\Catalog\Model\Layer\Filter\Item\DataBuilder $itemDataBuilder
* @param array $data
*/
public function __construct(
\Magento\Catalog\Model\Layer\Filter\ItemFactory $filterItemFactory,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Catalog\Model\Layer $layer,
\Magento\Catalog\Model\Layer\Filter\Item\DataBuilder $itemDataBuilder,
array $data = []
) {
parent::__construct($filterItemFactory, $storeManager, $layer, $itemDataBuilder, $data);
$this->_requestVar = 'is_brands';
}
/**
* @param \Magento\Framework\App\RequestInterface $request
* @return $this
*/
public function apply(\Magento\Framework\App\RequestInterface $request)
{
$filter = $request->getParam($this->getRequestVar(), null);
if (is_null($filter)) {
return $this;
}
$this->_activeFilter = true;
$filter = $filter;
$collection = $this->getLayer()->getProductCollection();
if ($filter == self::FILTER_IS_BRANDS) {
// $select->where('`e`.`brands` IS NOT NULL');
$collection->addAttributeToFilter('brands',array('gteq','1'));
} else {
// $select->where('(`e`.`brands` IS NULL OR `e`.`brands` = 0)');
$collection->addAttributeToFilter('brands',array('lt','1'));
}
$this->getLayer()->getState()->addFilter(
$this->_createItem($this->getLabel($filter), $filter)
);
return $this;
}
/**
* Get filter name
*
* @return string
*/
public function getName()
{
return __('Is Brands');
}
/**
* Get data array for building status filter items
*
* @return array
*/
protected function _getItemsData()
{
// if ($this->getLayer()->getProductCollection()->getFlag(self::IN_STOCK_COLLECTION_FLAG)) {
// return [];
// }
$data = [];
foreach ($this->getStatuses() as $status) {
$data[] = [
'label' => $this->getLabel($status),
'value' => $status,
'count' => $this->getProductsCount($status)
];
}
return $data;
}
/**
* get available statuses
* @return array
*/
public function getStatuses()
{
return [
self::FILTER_IS_BRANDS,
self::FILTER_IS_NOT_BRANDS
];
}
/**
* @return array
*/
public function getLabels()
{
return [
self::FILTER_IS_BRANDS => __('Is Brands'),
self::FILTER_IS_NOT_BRANDS => __('Is not Brands'),
];
}
/**
* @param $value
* @return string
*/
public function getLabel($value)
{
$labels = $this->getLabels();
if (isset($labels[$value])) {
return $labels[$value];
}
return '';
}
/**
* @param $value
* @return string
*/
public function getProductsCount($value)
{
$collection = $this->getLayer()->getProductCollection();
$select = clone $collection->getSelect();
// reset columns, order and limitation conditions
$select->reset(\Zend_Db_Select::COLUMNS);
$select->reset(\Zend_Db_Select::ORDER);
$select->reset(\Zend_Db_Select::LIMIT_COUNT);
$select->reset(\Zend_Db_Select::LIMIT_OFFSET);
// $select->where('stock_status_index.stock_status = ?', $value);
if ($value == self::FILTER_IS_BRANDS) {
// $select->where('`e`.`brands` IS NOT NULL');
$collection->addAttributeToFilter('brands',array('gteq','1'));
} else {
// $select->where('(`e`.`brands` IS NULL OR `e`.`brands` = 0)');
$collection->addAttributeToFilter('brands',array('lt','1'));
}
$select->columns(
[
'count' => new \Zend_Db_Expr("COUNT(e.entity_id)")
]
);
return $collection->getConnection()->fetchOne($select);
}
}
but I always get an error in a phtml when trying to get active filters
<?php $activeFilters = $block->getActiveFilters() ?>
Exception #0 (Magento\Framework\Exception\LocalizedException): The attribute model is not defined.