I have created an Extension to show a button named Shop By Collection on product page based on the condition that shop_by_collection dropdown attribute option is assigned to product.
This part is working fien and I can get a button with link and attribue code option id in the url.
After clicking the button I am redirected to a new custom collection page where I am showing all relevent products this is working fine but toolbar and layered navigation is not showing.
Here is my complete code, plz guide me what is the issue.
Block/ProductList.php
<?php
/**
* Mica ShopByCollection Product List Block
*/
namespace MicaShopByCollectionBlockCollection;
use MagentoCatalogBlockProductListProduct;
use MagentoCatalogBlockProductContext;
use MagentoCatalogModelLayerResolver;
use MagentoFrameworkDataHelperPostHelper;
use MagentoFrameworkUrlHelperData;
use MagentoFrameworkAppRequestInterface;
use MagentoFrameworkRegistry;
use MagentoCatalogModelResourceModelProductCollectionFactory;
use MagentoCatalogApiCategoryRepositoryInterface;
class ProductList extends ListProduct
{
/**
* @var RequestInterface
*/
protected $request;
/**
* @var Registry
*/
protected $registry;
/**
* @var CollectionFactory
*/
protected $productCollectionFactory;
/**
* @param Context $context
* @param PostHelper $postDataHelper
* @param Resolver $layerResolver
* @param CategoryRepositoryInterface $categoryRepository
* @param RequestInterface $request
* @param Registry $registry
* @param CollectionFactory $productCollectionFactory
* @param Data $urlHelper
* @param array $data
*/
public function __construct(
Context $context,
PostHelper $postDataHelper,
Resolver $layerResolver,
CategoryRepositoryInterface $categoryRepository,
RequestInterface $request,
Registry $registry,
CollectionFactory $productCollectionFactory,
Data $urlHelper,
array $data = []
) {
$this->request = $request;
$this->registry = $registry;
$this->productCollectionFactory = $productCollectionFactory;
parent::__construct(
$context,
$postDataHelper,
$layerResolver,
$categoryRepository,
$urlHelper,
$data
);
}
/**
* Get loaded product collection
*
* @return MagentoCatalogModelResourceModelProductCollection
*/
protected function _getProductCollection()
{
if ($this->_productCollection === null) {
// Try to get collection from layer first
$layer = $this->getLayer();
if ($layer) {
$this->_productCollection = $layer->getProductCollection();
}
// If layer collection is empty, create our own
if ($this->_productCollection === null || $this->_productCollection->count() === 0) {
$this->_productCollection = $this->productCollectionFactory->create();
$this->_productCollection->addAttributeToSelect('*');
$this->_productCollection->addMinimalPrice();
$this->_productCollection->addFinalPrice();
$this->_productCollection->addTaxPercents();
$this->_productCollection->addUrlRewrite();
$this->_productCollection->addStoreFilter();
}
// Apply shop_by_collection filter
$attributeValue = $this->request->getParam('attribute_value');
if ($attributeValue) {
// Add the filter directly to the collection
$this->_productCollection->addAttributeToFilter('shop_by_collection', $attributeValue);
}
// Filter out configurable child products
// This joins the collection with the super link table and excludes any
// products that are children of configurable products
$this->_productCollection->getSelect()->joinLeft(
['super_link' => $this->_productCollection->getTable('catalog_product_super_link')],
'e.entity_id = super_link.product_id',
[]
)->where('super_link.product_id IS NULL');
}
return $this->_productCollection;
}
}
Block/CollectionButton.php
<?php
/**
* Mica ShopByCollection Button Block
*/
namespace MicaShopByCollectionBlockProduct;
use MagentoCatalogModelProduct;
use MagentoFrameworkRegistry;
use MagentoFrameworkViewElementTemplate;
use MagentoFrameworkViewElementTemplateContext;
class CollectionButton extends Template
{
/**
* @var Registry
*/
private $registry;
/**
* @param Context $context
* @param Registry $registry
* @param array $data
*/
public function __construct(
Context $context,
Registry $registry,
array $data = []
) {
$this->registry = $registry;
parent::__construct($context, $data);
}
/**
* Get current product
*
* @return Product|null
*/
public function getProduct()
{
return $this->registry->registry('current_product');
}
/**
* Check if product has collection attribute
*
* @return bool
*/
public function hasCollection()
{
$product = $this->getProduct();
if ($product && $product->getData('shop_by_collection')) {
return true;
}
return false;
}
/**
* Get collection attribute value
*
* @return string
*/
public function getCollectionValue()
{
$product = $this->getProduct();
if ($product) {
$attributeValue = $product->getAttributeText('shop_by_collection');
if ($attributeValue) {
return $attributeValue;
}
return $product->getData('shop_by_collection');
}
return '';
}
/**
* Get collection URL
*
* @return string
*/
public function getCollectionUrl()
{
$product = $this->getProduct();
if ($product) {
// Log the attribute value for debugging
$this->_logger->debug('Collection attribute value: ' . $product->getData('shop_by_collection'));
return $this->getUrl('collection/collection/view', [
'attribute_value' => $product->getData('shop_by_collection')
]);
}
return '#';
}
/**
* Get collection attribute options for debugging
*
* @return array
*/
public function getAttributeOptions()
{
$options = [];
$product = $this->getProduct();
if ($product) {
$attribute = $product->getResource()->getAttribute('shop_by_collection');
if ($attribute) {
foreach ($attribute->getOptions() as $option) {
$options[$option->getValue()] = $option->getLabel();
}
}
}
return $options;
}
}
Controller/Collection/View.php
<?php
/**
* Mica ShopByCollection Collection View Controller
*/
namespace MicaShopByCollectionControllerCollection;
use MagentoFrameworkAppActionAction;
use MagentoFrameworkAppActionContext;
use MagentoFrameworkAppRequestInterface;
use MagentoFrameworkViewResultPageFactory;
use MagentoFrameworkRegistry;
use MagentoCatalogModelLayerResolver;
class View extends Action
{
/**
* @var PageFactory
*/
protected $resultPageFactory;
/**
* @var Registry
*/
protected $registry;
/**
* @var Resolver
*/
protected $layerResolver;
/**
* @param Context $context
* @param PageFactory $resultPageFactory
* @param Registry $registry
* @param Resolver $layerResolver
*/
public function __construct(
Context $context,
PageFactory $resultPageFactory,
Registry $registry,
Resolver $layerResolver
) {
$this->resultPageFactory = $resultPageFactory;
$this->registry = $registry;
$this->layerResolver = $layerResolver;
parent::__construct($context);
}
/**
* Collection view action
*
* @return MagentoFrameworkControllerResultInterface
*/
public function execute()
{
// FIXED: Use a valid layer type - 'search' is always available
$this->layerResolver->create('search');
$resultPage = $this->resultPageFactory->create();
$attributeValue = $this->getRequest()->getParam('attribute_value');
// Register attribute value for use in blocks
if ($attributeValue) {
$this->registry->register('current_collection_attribute_value', $attributeValue);
$attributeText = $this->getAttributeText($attributeValue);
$resultPage->getConfig()->getTitle()->set(__('Products in %1 Collection', $attributeText));
} else {
$resultPage->getConfig()->getTitle()->set(__('Collection'));
}
return $resultPage;
}
/**
* Get attribute text value
*
* @param string $attributeValue
* @return string
*/
private function getAttributeText($attributeValue)
{
// Get attribute text from option value
$objectManager = MagentoFrameworkAppObjectManager::getInstance();
$attributeRepository = $objectManager->get(MagentoEavApiAttributeRepositoryInterface::class);
try {
$attribute = $attributeRepository->get('catalog_product', 'shop_by_collection');
foreach ($attribute->getOptions() as $option) {
if ($option->getValue() == $attributeValue) {
return $option->getLabel();
}
}
} catch (Exception $e) {
return $attributeValue;
}
return $attributeValue;
}
}
etc/frontend/routes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="mica_collection" frontName="collection">
<module name="Mica_ShopByCollection" />
</route>
</router>
</config>
etc/di/xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="MagentoCatalogModelLayerSearchFilterableAttributeList">
<plugin name="mica_collection_filter_search" type="MicaShopByCollectionPluginLayerCollectionFilterList" />
</type>
<type name="MagentoCatalogModelLayerCategoryFilterableAttributeList">
<plugin name="mica_collection_filter_category" type="MicaShopByCollectionPluginLayerCollectionFilterList" />
</type>
</config>
Model/CollectionProducts.php
<?php
/**
* Mica ShopByCollection Collection Products Model
*/
namespace MicaShopByCollectionModel;
use MagentoCatalogModelResourceModelProductCollection;
use MagentoCatalogModelResourceModelProductCollectionFactory;
use MagentoFrameworkAppRequestInterface;
class CollectionProducts
{
/**
* @var CollectionFactory
*/
protected $collectionFactory;
/**
* @var RequestInterface
*/
protected $request;
/**
* @param CollectionFactory $collectionFactory
* @param RequestInterface $request
*/
public function __construct(
CollectionFactory $collectionFactory,
RequestInterface $request
) {
$this->collectionFactory = $collectionFactory;
$this->request = $request;
}
/**
* Get product collection filtered by attribute value
*
* @return Collection
*/
public function getFilteredCollection()
{
$collection = $this->collectionFactory->create();
$collection->addAttributeToSelect('*');
$attributeValue = $this->request->getParam('attribute_value');
if ($attributeValue) {
$collection->addAttributeToFilter('shop_by_collection', $attributeValue);
}
return $collection;
}
}
view/frontend/layout/mica_collection_collection_view.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<update handle="catalog_category_view_type_layered"/>
<body>
<referenceContainer name="content">
<!-- Product listing -->
<block class="MicaShopByCollectionBlockCollectionProductList"
name="collection.products"
template="Magento_Catalog::product/list.phtml"
cacheable="false">
<container name="category.product.list.additional" as="additional" />
<block class="MagentoFrameworkViewElementRendererList" name="category.product.type.details.renderers" as="details.renderers">
<block class="MagentoFrameworkViewElementTemplate" name="default" as="default"/>
</block>
<block class="MagentoCatalogBlockProductProductListToolbar" name="product_list_toolbar" template="Magento_Catalog::product/list/toolbar.phtml">
<block class="MagentoThemeBlockHtmlPager" name="product_list_toolbar_pager"/>
</block>
<action method="setToolbarBlockName">
<argument name="name" xsi:type="string">product_list_toolbar</argument>
</action>
</block>
</referenceContainer>
<referenceContainer name="sidebar.main">
<block class="MagentoLayeredNavigationBlockNavigationCategory" name="catalog.leftnav" template="Magento_LayeredNavigation::layer/view.phtml">
<block class="MagentoLayeredNavigationBlockNavigationState" name="catalog.navigation.state" as="state" />
<block class="MagentoLayeredNavigationBlockNavigationFilterRenderer" name="catalog.navigation.renderer" as="renderer" template="Magento_LayeredNavigation::layer/filter.phtml"/>
</block>
</referenceContainer>
<referenceContainer name="head.additional">
<block class="MagentoFrameworkViewElementTemplate" name="mica.shopbycollection.custom.css" template="Mica_ShopByCollection::custom-styles.phtml"/>
</referenceContainer>
</body>
</page>
view/frontend/layout/catalog_product_view.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="product.info.price">
<block class="MicaShopByCollectionBlockProductCollectionButton"
name="product.info.collection.button"
template="Mica_ShopByCollection::product/collection_button.phtml"
after="-" />
</referenceContainer>
</body>
</page>
view/frontend/templates/collection_button.phtml
<?php
/**
* @var $block MicaShopByCollectionBlockProductCollectionButton
*/
?>
<?php if ($block->hasCollection()): ?>
<div class="collection-button-container">
<a href="<?= $block->escapeUrl($block->getCollectionUrl()) ?>" class="action primary collection-button"
title="<?= $block->escapeHtml(__('Shop by %1 Collection', $block->getCollectionValue())) ?>">
<span><?= $block->escapeHtml(__('Shop by %1 Collection', $block->getCollectionValue())) ?></span>
</a>
</div>