如何在Magento产品列表中显示每种颜色的可配置产品?

时间:2010-05-17 07:02:52

标签: php magento

我有一个可配置的产品,有多种不同的颜色和尺寸可供选择。我希望可配置产品每种颜色都出现一次。我的想法是将每种颜色的可配置产品的一个简单产品分配给可配置产品的类别。然后我想更改列表,以便(彩色)简单产品链接到它的主产品(可配置产品)。

另一种方法是,将可配置产品分配到一个类别,然后用不同颜色多次列出。但我认为这会很复杂。

解决方案

真诚地,我丢失了我的代码。但这是我如何管理它:

  1. 将所有从属产品的可见性设置为“目录”以便它们 出现在产品列表中
  2. 覆盖产品型号,它是getProductUrl函数:

    public function getProductUrl($ useSid = null) { $ product = $ this; $产品 - > loadParentProductIds();     $ parentIds = $ product-> getParentProductIds();

    if(count($ parentIds)> 0&& $ product-> getTypeId()== Mage_Catalog_Model_Product_Type :: TYPE_SIMPLE) {         $ parent = Mage :: getModel(“catalog / product”) - > setId($ parentIds [0]) - > load();         return $ this-> getUrlModel() - > getProductUrl($ parent,$ useSid); }

    返回$ this-> getUrlModel() - > getProductUrl($ product,$ useSid); }

  3. 这样每个从属产品都链接到它的主产品。棘手的部分是将属性附加到URL。您可以将#attributecode1 = value1& attributecode2 = value2添加到网址以预选属性选择框。我只有这部分快速&很脏,我很确定有人能做得更好。

    预选的示例:

    http://demo.magentocommerce.com/anashria-womens-premier-leather-sandal-7.html http://demo.magentocommerce.com/anashria-womens-premier-leather-sandal-7.html#502=43

3 个答案:

答案 0 :(得分:1)

我不明白为什么你不根据每种颜色的尺寸制作可配置的产品?这样你就不需要破解Magento的工作方式了。

如果您制作的简单产品是可在前端看到的可配置产品的一部分,则它不会链接到可配置产品(如果它是其中一部分)(如您所知)。这对你来说真的没有意义,因为如果你的可配置产品是基于尺寸和颜色的,那么简单的产品将具有一定的尺寸和颜色。

如果您为每种衬衫颜色制作了可配置的产品,那么您将完成,功能齐全且无黑客攻击。然后,您还可以使用相关产品来展示其他衬衫颜色。

黑客越少越好。这是我的意见。

答案 1 :(得分:1)

在其他人需要在Magento 2中执行此操作的情况下,请对此线程进行坏掉。

以下是我的解决方案。请记住,它很hacky,并且会破坏很多东西,因此仅当您是Magento开发人员并且知道自己在做什么并且可以修复或忍受此代码的负面影响时,才可以使用。

  

registration.php

<?php
use \Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Antti_ConfigurableProductSplitter', __DIR__);
  

etc / module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Antti_ConfigurableProductSplitter" >
        <sequence>
            <module name="Magento_Catalog" />
        </sequence>
    </module>
</config>
  

etc / frontend / events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="catalog_block_product_list_collection">
        <observer name="cps_catalog_block_product_list_collection" instance="Antti\ConfigurableProductSplitter\Observer\CatalogBlockProductCollectionBeforeToHtmlObserver" shared="false" />
    </event>
    <event name="cps_product_data_merge_after">
        <observer name="cps_product_data_merge_after" instance="Antti\ConfigurableProductSplitter\Observer\SetColorPreselectedAfterProductDataMerge" shared="false" />
    </event>
</config>
  

Observer / CatalogBlockProductCollectionBeforeToHtmlObserver.php

<?php
namespace Antti\ConfigurableProductSplitter\Observer;

use Magento\Framework\Event\ObserverInterface;
use Antti\ConfigurableProductSplitter\Model\ProductCollectionSplitter;

class CatalogBlockProductCollectionBeforeToHtmlObserver implements ObserverInterface
{
    /**
     * @var ProductCollectionSplitter
     */
    private $productSplitter;

    /**
     * CatalogBlockProductCollectionBeforeToHtmlObserver constructor.
     *
     * @param ProductCollectionSplitter $productSplitter
     */
    public function __construct(
        ProductCollectionSplitter $productSplitter
    ) {
        $this->productSplitter = $productSplitter;
    }

    /**
     * @param \Magento\Framework\Event\Observer $observer
     *
     * @return $this
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $productCollection = $observer->getEvent()->getCollection();
        if ($productCollection instanceof \Magento\Framework\Data\Collection) {
            if (!$productCollection->isLoaded()) {
                $productCollection->load();
            }
            $this->productSplitter->splitConfigurables($productCollection);
        }

        return $this;
    }
}
  

Observer / SetColorPreselectedAfterProductDataMerge.php

<?php
namespace Antti\ConfigurableProductSplitter\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Eav\Model\Config as EavConfig;

class SetColorPreselectedAfterProductDataMerge implements ObserverInterface
{
    /**
     * @var EavConfig
     */
    private $eavConfig;

    /**
     * ProductDataMerger constructor.
     *
     * @param EavConfig $eavConfig
     */
    public function __construct(
        EavConfig $eavConfig
    ) {
        $this->eavConfig = $eavConfig;
    }

    /**
     * @param \Magento\Framework\Event\Observer $observer
     *
     * @return $this
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $product = $observer->getEvent()->getSimple();
        $merged = $observer->getEvent()->getMerged();

        $this->setColorPreselected($merged, $product->getColor());

        return $this;
    }

    /**
     * @param ProductInterface $product
     * @param int $color
     *
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    private function setColorPreselected(ProductInterface &$product, int $color)
    {
        $attribute = $this->eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, 'color');

        $preconfiguredValues = new \Magento\Framework\DataObject();
        $preconfiguredValues->setData('super_attribute', [$attribute->getId() => $color]);
        $product->setPreconfiguredValues($preconfiguredValues);

        // TODO: should test whether this works if there is no url rewrite
        $product->setRequestPath(sprintf('%s#%d=%d', $product->getRequestPath(), $attribute->getId(), $color));
    }
}
  

Model / ProductDataMerger.php

<?php
namespace Antti\ConfigurableProductSplitter\Model;

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Framework\EntityManager\EventManager;

class ProductDataMerger
{
    /**
     * @var EventManager
     */
    private $eventManager;

    /**
     * @param EventManager $eventManager
     */
    public function __construct(
        EventManager $eventManager
    ) {
        $this->eventManager = $eventManager;
    }

    /**
     * @param ProductInterface $product
     * @param ProductInterface $parentProduct
     *
     * @return ProductInterface
     */
    public function merge(ProductInterface $product, ProductInterface $parentProduct)
    {
        $merged = clone $parentProduct;
        $merged->setParentId($merged->getId());
        $merged->setId($product->getId());

        $this->setImageFromChildProduct($merged, $product);

        $this->eventManager->dispatch(
            'cps_product_data_merge_after',
            ['merged' => $merged, 'simple' => $product, 'configurable' => $parentProduct]
        );

        return $merged;
    }

    /**
     * @param ProductInterface $product
     * @param ProductInterface $childProduct
     */
    public function setImageFromChildProduct(ProductInterface &$product, ProductInterface $childProduct)
    {
        foreach (['image', 'small_image', 'thumbnail'] as $imageType) {
            if ($childProduct->getData($imageType) && $childProduct->getData($imageType) !== 'no_selection') {
                $product->setData($imageType, $childProduct->getData($imageType));
            } else {
                $product->setData($imageType, $childProduct->getData('image'));
            }
        }
    }
}
  

Model / ProductCollectionSplitter.php

<?php
namespace Antti\ConfigurableProductSplitter\Model;

use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
use Antti\ConfigurableProductSplitter\Model\ProductDataMerger;
use Magento\Catalog\Model\Layer\Resolver;

class ProductCollectionSplitter
{
    /**
     * @var \Magento\Catalog\Model\Layer
     */
    private $catalogLayer;

    /**
     * @var ProductDataMerger
     */
    private $productDataMerger;

    /**
     * ProductCollectionSplitter constructor.
     *
     * @param Resolver $layerResolver
     * @param ProductDataMerger $productDataMerger
     */
    public function __construct(
        Resolver $layerResolver,
        ProductDataMerger $productDataMerger
    ) {
        $this->catalogLayer = $layerResolver->get();
        $this->productDataMerger = $productDataMerger;
    }

    /**
     * @param \Magento\Framework\Data\Collection $collection
     *
     * @return $this
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function splitConfigurables(\Magento\Framework\Data\Collection $collection)
    {
        $items = $collection->getItems();

        if (sizeof($items) == 0) {
            return $this;
        }

        $configurables = $otherProducts = [];

        $colorFilterValue = $this->getCurrentColorFilterValue();

        foreach ($items as $index => $product) {
            if ($product->getTypeId() === Configurable::TYPE_CODE) {
                /** @var \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection $childProducts */
                $childProducts = $product->getTypeInstance()->getUsedProductCollection($product);
                if ($colorFilterValue !== null) {
                    $childProducts->addAttributeToFilter('color', ['eq' => $colorFilterValue]);
                }
                $childProducts->groupByAttribute('color');

                foreach ($childProducts as $childProduct) {
                    $childProduct->setParentId($product->getId());
                    $otherProducts[] = $childProduct;
                }

                $configurables[$product->getId()] = $product;
            } else {
                $otherProducts[] = $product;
            }

            $collection->removeItemByKey($index);
        }

        foreach ($otherProducts as $product) {
            if ($product->getParentId() && isset($configurables[$product->getParentId()])) {
                $product = $this->productDataMerger->merge($product, $configurables[$product->getParentId()]);
            }
            $collection->addItem($product);
        }

        return $this;
    }

    /**
     * @return string|null
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    private function getCurrentColorFilterValue()
    {
        /** @var \Magento\Catalog\Model\Layer\Filter\Item $filter */
        foreach ($this->catalogLayer->getState()->getFilters() as $filter) {
            if($filter->getFilter()->getAttributeModel()->getName() == 'color') {
                return $filter->getValueString();
            }
        }

        return null;
    }
}

已知问题:

  • 由于加载后修改了收集项目,收集计数将为 无效,这可能会导致其他问题。
  • 该集合中的产品ID也将无效,因为可配置商品的ID被简单产品的ID代替。
  • 如果该收藏集将再次加载到其他地方,则不会拆分可配置的产品。
  • 每页产品限制器不再起作用。
  • 产品列表上的产品计数无效。
  • 第三方搜索模块(例如Klevu)可能不起作用
  • 其他第三方模块可能会在实现过程中出现问题。
  • 产品库存数据,评论等在产品列表上已损坏(尽管很容易在前端修复)。
  • 不确定在没有url重写的情况下实现是否可以正常工作(虽然应该很容易解决)。
  • 其他我可能不知道的问题。

答案 2 :(得分:0)

一种方法是制作目录号的大小和颜色部分(或者您为产品使用的任何唯一识别号)

因此,假设您有一个有2种颜色和3种尺寸的小部件,它的目录号是“qwe123”。您可以在系统中输入以下2个项目以及相应的图像。我假设你已经有办法处理尺寸了。

qwe123-red
qwe123-blue

这样做没有额外的编程,但是如果你想链接到产品页面中可用的其他颜色,那么你将需要解析目录编号的第一部分并搜索匹配的。