Question

We want to implement the attribute group name on the compare product page and separate all attributes based on the attribute group.

We use the following code to show the attribute group name on the specifications section on the product page.

How can we implement this on the product compare page?

CODE;

<?php
namespace AttributeGroup\Module\Block\Product;

class Specification extends \Magento\Catalog\Block\Product\View
{
     /**
      * @var \Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory
      */
     protected $groupCollectionFactory;

     public function __construct(
         \Magento\Catalog\Block\Product\Context $context,
         \Magento\Framework\Url\EncoderInterface $urlEncoder,
         \Magento\Framework\Json\EncoderInterface $jsonEncoder,
         \Magento\Framework\Stdlib\StringUtils $string,
         \Magento\Catalog\Helper\Product $productHelper,
         \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig,
         \Magento\Framework\Locale\FormatInterface $localeFormat,
         \Magento\Customer\Model\Session $customerSession,
         \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
         \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
         \Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory $groupCollectionFactory,
         array $data = []
    ) {
        parent::__construct($context, $urlEncoder, $jsonEncoder, $string,
        $productHelper, $productTypeConfig, $localeFormat, $customerSession,
        $productRepository, $priceCurrency, $data);
        $this->groupCollectionFactory = $groupCollectionFactory;
    }


    public function getAttributeLabels()
     {
    $product = $this->getProduct();

    $attributeSetId = $product->getAttributeSetId();

    $groupCollection = $this->groupCollectionFactory->create()
        ->setAttributeSetFilter($attributeSetId)
        ->setSortOrder()
        ->load();

    $html = '';
    foreach ($groupCollection as $group) {
        $attributes = $product->getAttributes($group->getId(), true);



        $new_html = "";
        foreach ($attributes as $key => $attribute) {
            if($attribute->getIsVisibleOnFront() && $attribute->getFrontend()->getValue($product) !="" && $attribute->getFrontend()->getValue($product) !="Non"){

                $new_html .= '<div class="product-specs-list-item">
                                <dt class="product-specs-item-title">' . $attribute->getStoreLabel(). '</dt>
                                <dl class="product-specs-item-spec">' . $attribute->getFrontend()->getValue($product) . '</dl>              
                            </div>';

            }
        }

        if($new_html!=''){

            $html .= "<div class='grid-section-xs-specification active'>";
            $html .= '<h3 class="noselect toggle-specification">' . $group->getData('attribute_group_name').'</h3>';
            $html .= "<dl class='product-specs'>";
            $html .= $new_html;
            $html .= "</dl>
            </div>";
        }

    }

    return $html;
}
}?>
Was it helpful?

Solution

I have worked out a solution for your problem. To make this happening, I have taken over the Magento template for the compare product listing.

The template gains awareness of the product attributes' groups from the attributes Magento has come up with the function below:

  /**
     * @param \Magento\Catalog\Api\Data\ProductInterface $product
     * @return \Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\Collection
     */
    public function findGroupListForProduct(\Magento\Catalog\Api\Data\ProductInterface $product, $attributes)
    {
        $groupCollection = $this->_groupCollection->create();
        $groupCollection->addFieldToFilter('main_table.attribute_set_id', $product->getAttributeSetId());

        $attributeIds = [];
        foreach ($attributes as $attribute) {
            $attributeIds[] = $attribute->getId();
        }

        $groupCollection->getSelect()->join(
            ['entity_table' => $groupCollection->getTable('eav_entity_attribute')],
            sprintf('entity_table.attribute_group_id=main_table.attribute_group_id and entity_table.attribute_id in (%s)', implode(',', $attributeIds)),
            []
        )->group('main_table.attribute_group_id');

        return $groupCollection;
    }

and then, a second function brings the attributes for a given group

/**
         * @param $groupId
         * @param $attributes
         * @return \Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection
         */
        public function getAttributesListInGroup($groupId, $attributes)
            {
                $attributeIds = [];
                foreach ($attributes as $attribute) {
                    $attributeIds[] = $attribute->getId();
                }

                $collection = $this->collectionFactory->create();
                $collection->addFieldToFilter('main_table.attribute_id', ['in' => $attributeIds]);

                $collection->getSelect()->join(
                    ['entity_table' => $collection->getTable('eav_entity_attribute')],
                    'entity_table.attribute_id=main_table.attribute_id',
                    []
                )->where('entity_table.attribute_group_id=?', $groupId);

                return $collection;
            }

I put a link for the whole module as I find it more reliable to convey my solution.

https://bitbucket.org/magstaging/productcompare/src/master/

My solution eventually uses a viewModel for readability benefits. I chose this solution as the template and its way to retrieve its data are not coupled. Hope this resolve your problem

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top