Podcast #128: We chat with Kent C Dodds about why he loves React and discuss what life was like in the dark days before Git. Listen now.
2 deleted 2766 characters in body
source | link

First of all Crossel product section is default showed at Cart page and it is showing showing depends on last add cart items.

Suppose, you want to add Crosssellsection at product detail page and want to show current product's Crosssellproducts then you need to create an extension.

<?php
namespace {VendorName}\{ModuleName}\Block\Cart;
\Block;
use Magento\CatalogInventory\Helper\Stock as StockHelper;
class Crosssell extends \Magento\Catalog\Block\Product\AbstractProduct
{
    protected $_maxItemCount = 4;
    protected $_checkoutSession;
    protected $_productVisibility;
    protected $stockHelper;
    protected $_coreRegistry;
    protected $_productLinkFactory;

    protected $_itemRelationsList;

    public function __construct(
        \Magento\Catalog\Block\Product\Context $context,
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Catalog\Model\Product\Visibility $productVisibility,
        \Magento\Catalog\Model\Product\LinkFactory $productLinkFactory,
        \Magento\Quote\Model\Quote\Item\RelatedProducts $itemRelationsList,
        StockHelper $stockHelper,
        array $data = []
    ) {
        $this->_checkoutSession = $checkoutSession;
        $this->_productVisibility = $productVisibility;
        $this->_productLinkFactory = $productLinkFactory;
        $this->_itemRelationsList = $itemRelationsList;
        $this->stockHelper = $stockHelper;
        parent::__construct(/**
         * Crosssell item $context,collection
            $data*
      * @var );\Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection
        $this->_isScopePrivate = true;*/
        $this->_coreRegistry = $context->getRegistry();
   protected }$_itemCollection;

    /**
     * GetPrepare crosssell items data
     *
     * @return array\Magento\Catalog\Block\Product\ProductList\Crosssell
     */
    publicprotected function getItems_prepareData()
    {
        $items$product = $this->getData>_coreRegistry->registry('items''product');
        if/* ($items@var ===$product null)\Magento\Catalog\Model\Product {*/
            $items = [];
            $ninProductIds = $this->_getCartProductIds();
            if ($ninProductIds) {
                $currentProduct>_itemCollection = (int)$this$product->getProduct>getCrossSellProductCollection()->getId();
                if >addAttributeToSelect($currentProduct) {
                    $collection = $this->_getCollection()>_catalogConfig->addProductFilter>getProductAttributes($currentProduct);
                    if (!empty($ninProductIds)->setPositionOrder() {
                        $collection->addExcludeProductFilter>addStoreFilter($ninProductIds);
                    }
                    $collection$this->setPositionOrder()>_itemCollection->load();

                    foreach ($collection$this->_itemCollection as $item$product) {
                        $ninProductIds[] = $item$product->getId>setDoNotUseCategoryId(true);
                        $items[] = $item;
                    }
                }

                if (count($items) < $this->_maxItemCount) {
                    $filterProductIds = array_merge(
                       return $this->_getCartProductIds(),$this;
                        $this->_itemRelationsList->getRelatedProductIds($this->getQuote()->getAllItems())}
                    );
                    $collection = $this->_getCollection()->addProductFilter(/**
                    * Before rendering html $filterProductIdsprocess
                 * Prepare items )->addExcludeProductFilter(collection
                        $ninProductIds*
                  * @return )->setPageSize(\Magento\Catalog\Block\Product\ProductList\Crosssell
                        $this->_maxItemCount - count($items)*/
                  protected function )->setGroupBy()->setPositionOrder()->load_beforeToHtml();
                    foreach ($collection as $item) {
                        $items[] = $item;
                    }
                }
            }

            $this->setData>_prepareData('items', $items);
        }
        return $items;parent::_beforeToHtml();
    }

    /**
     * CountRetrieve crosssell items collection
     *
     * @return int
     * @codeCoverageIgnore\Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection
     */
    public function getItemCountgetItems()
    {
        return count($this->getItems());>_itemCollection;
    }

    public function getProduct()
    {
        return $this->_coreRegistry->registry('product');
    }
    protected function _getCartProductIds_toHtml()
    {
        $ids = $this->getData('_cart_product_ids');
       /* if ($ids === null) {
      product is out stock then render $idshtml = [];*/
            foreachif (!$this->getQuote()>_coreRegistry->getAllItems>registry() as $item'product') {
                $product = $item->getProduct>isSaleable();
                if ($product) {
                    $ids[] =return $product->getId();'';
                }
            }
           return $this->setDataparent::_toHtml('_cart_product_ids', $ids);
        }
        return $ids;
    }

    protected function _getLastAddedProductId()}
   

Now, you need create layout file catalog_product_view.xml at

app/design/frontend/{Vendor}/{mytheme}/{VendorName}/{ModuleName}/layout

Now add below code at this layout files:

<?xml {version="1.0"?>
       <page returnlayout="1column" $this->_checkoutSessionxmlns:xsi="http://www.w3.org/2001/XMLSchema->getLastAddedProductId(true);
   instance" }

    xsi:noNamespaceSchemaLocation="urn:magento:framework:View/**
     * Get quote instance
     *
     * @return \Magento\Quote\Model\Quote
     * @codeCoverageIgnore
     *Layout/
    public function getQuote()etc/page_configuration.xsd">
   <referenceContainer {name="content.aside">
        return $this->_checkoutSession->getQuote();
   <block class="{VendorName}

  \{ModuleName}\Block\Product\ProductList\Crosssell" name="product.info.upsell" template="Magento_Catalog::product/**list/items.phtml">
     * Get crosssell products collection<arguments>
     *
     * @return \Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection
   <argument name="type" *xsi:type="string">upsell</
    protected function _getCollection()
    {argument>
        /** @var \Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection $collection *</
        $collection = $this->_productLinkFactory->create()->useCrossSellLinks()->getProductCollection()->setStoreId(
            $this->_storeManager->getStore()->getId()
        )->addStoreFilter()->setPageSize(arguments>
            $this->_maxItemCount
     <block class="Magento\Catalog\Block\Product\ProductList\Item\Container" name="crosssell.product.addto" )->setVisibility(as="addto">
            $this->_productVisibility->getVisibleInCatalogIds()
       <block );class="Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare"
        $this->_addProductAttributesAndPrices($collection);

        return $collection;
   name="upsell.product.addto.compare" }as="compare"
    protected function _toHtml()
    {
        /* if template="Magento_Catalog::product is out stock then render html  */list/addto/compare.phtml"/>
        if (!$this->getProduct()->isSaleable()) {</block>
            return '';</block>
    </referenceContainer>    }
      </page>  return parent::_toHtml();
    }
}

First of all Crossel product section is default showed at Cart page and it is showing showing depends on last add cart items.

Suppose, you want to add Crosssellsection at product detail page and want to show current product's Crosssellproducts then you need to create an extension.

<?php
namespace {VendorName}\{ModuleName}\Block\Cart;

use Magento\CatalogInventory\Helper\Stock as StockHelper;
class Crosssell extends \Magento\Catalog\Block\Product\AbstractProduct
{
    protected $_maxItemCount = 4;
    protected $_checkoutSession;
    protected $_productVisibility;
    protected $stockHelper;
    protected $_coreRegistry;
    protected $_productLinkFactory;

    protected $_itemRelationsList;

    public function __construct(
        \Magento\Catalog\Block\Product\Context $context,
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Catalog\Model\Product\Visibility $productVisibility,
        \Magento\Catalog\Model\Product\LinkFactory $productLinkFactory,
        \Magento\Quote\Model\Quote\Item\RelatedProducts $itemRelationsList,
        StockHelper $stockHelper,
        array $data = []
    ) {
        $this->_checkoutSession = $checkoutSession;
        $this->_productVisibility = $productVisibility;
        $this->_productLinkFactory = $productLinkFactory;
        $this->_itemRelationsList = $itemRelationsList;
        $this->stockHelper = $stockHelper;
        parent::__construct(
            $context,
            $data
        );
        $this->_isScopePrivate = true;
        $this->_coreRegistry = $context->getRegistry();
    }

    /**
     * Get crosssell items
     *
     * @return array
     */
    public function getItems()
    {
        $items = $this->getData('items');
        if ($items === null) {
            $items = [];
            $ninProductIds = $this->_getCartProductIds();
            if ($ninProductIds) {
                $currentProduct = (int)$this->getProduct()->getId();
                if ($currentProduct) {
                    $collection = $this->_getCollection()->addProductFilter($currentProduct);
                    if (!empty($ninProductIds)) {
                        $collection->addExcludeProductFilter($ninProductIds);
                    }
                    $collection->setPositionOrder()->load();

                    foreach ($collection as $item) {
                        $ninProductIds[] = $item->getId();
                        $items[] = $item;
                    }
                }

                if (count($items) < $this->_maxItemCount) {
                    $filterProductIds = array_merge(
                        $this->_getCartProductIds(),
                        $this->_itemRelationsList->getRelatedProductIds($this->getQuote()->getAllItems())
                    );
                    $collection = $this->_getCollection()->addProductFilter(
                        $filterProductIds
                    )->addExcludeProductFilter(
                        $ninProductIds
                    )->setPageSize(
                        $this->_maxItemCount - count($items)
                    )->setGroupBy()->setPositionOrder()->load();
                    foreach ($collection as $item) {
                        $items[] = $item;
                    }
                }
            }

            $this->setData('items', $items);
        }
        return $items;
    }

    /**
     * Count items
     *
     * @return int
     * @codeCoverageIgnore
     */
    public function getItemCount()
    {
        return count($this->getItems());
    }

    public function getProduct()
    {
        return $this->_coreRegistry->registry('product');
    }
    protected function _getCartProductIds()
    {
        $ids = $this->getData('_cart_product_ids');
        if ($ids === null) {
            $ids = [];
            foreach ($this->getQuote()->getAllItems() as $item) {
                $product = $item->getProduct();
                if ($product) {
                    $ids[] = $product->getId();
                }
            }
            $this->setData('_cart_product_ids', $ids);
        }
        return $ids;
    }

    protected function _getLastAddedProductId()
    {
        return $this->_checkoutSession->getLastAddedProductId(true);
    }

    /**
     * Get quote instance
     *
     * @return \Magento\Quote\Model\Quote
     * @codeCoverageIgnore
     */
    public function getQuote()
    {
        return $this->_checkoutSession->getQuote();
    }

    /**
     * Get crosssell products collection
     *
     * @return \Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection
     */
    protected function _getCollection()
    {
        /** @var \Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection $collection */
        $collection = $this->_productLinkFactory->create()->useCrossSellLinks()->getProductCollection()->setStoreId(
            $this->_storeManager->getStore()->getId()
        )->addStoreFilter()->setPageSize(
            $this->_maxItemCount
        )->setVisibility(
            $this->_productVisibility->getVisibleInCatalogIds()
        );
        $this->_addProductAttributesAndPrices($collection);

        return $collection;
    }
    protected function _toHtml()
    {
        /* if product is out stock then render html  */
        if (!$this->getProduct()->isSaleable()) {
            return '';
        }
        return parent::_toHtml();
    }
}

Suppose, you want to add Crosssellsection at product detail page and want to show current product's Crosssellproducts then you need to create an extension.

<?php
namespace {VendorName}\{ModuleName}\Block;

class Crosssell extends \Magento\Catalog\Block\Product\AbstractProduct
{
    /**
     * Crosssell item collection
     *
     * @var \Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection
     */
    protected $_itemCollection;

    /**
     * Prepare crosssell items data
     *
     * @return \Magento\Catalog\Block\Product\ProductList\Crosssell
     */
    protected function _prepareData()
    {
        $product = $this->_coreRegistry->registry('product');
        /* @var $product \Magento\Catalog\Model\Product */

        $this->_itemCollection = $product->getCrossSellProductCollection()->addAttributeToSelect(
            $this->_catalogConfig->getProductAttributes()
        )->setPositionOrder()->addStoreFilter();

        $this->_itemCollection->load();

        foreach ($this->_itemCollection as $product) {
            $product->setDoNotUseCategoryId(true);
        }

        return $this;
    }

    /**
     * Before rendering html process
     * Prepare items collection
     *
     * @return \Magento\Catalog\Block\Product\ProductList\Crosssell
     */
    protected function _beforeToHtml()
    {
        $this->_prepareData();
        return parent::_beforeToHtml();
    }

    /**
     * Retrieve crosssell items collection
     *
     * @return \Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection
     */
    public function getItems()
    {
        return $this->_itemCollection;
    }

    protected function _toHtml()
    {
            /* if product is out stock then render html  */
            if (!$this->_coreRegistry->registry('product')->isSaleable()) {
                return '';
            }
            return parent::_toHtml();
    }


}

Now, you need create layout file catalog_product_view.xml at

app/design/frontend/{Vendor}/{mytheme}/{VendorName}/{ModuleName}/layout

Now add below code at this layout files:

<?xml version="1.0"?>
<page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<referenceContainer name="content.aside">
    <block class="{VendorName}\{ModuleName}\Block\Product\ProductList\Crosssell" name="product.info.upsell" template="Magento_Catalog::product/list/items.phtml">
        <arguments>
            <argument name="type" xsi:type="string">upsell</argument>
        </arguments>
        <block class="Magento\Catalog\Block\Product\ProductList\Item\Container" name="crosssell.product.addto" as="addto">
            <block class="Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare"
                   name="upsell.product.addto.compare" as="compare"
                   template="Magento_Catalog::product/list/addto/compare.phtml"/>
        </block>
    </block>
 </referenceContainer>    
 </page>       
1
source | link

First of all Crossel product section is default showed at Cart page and it is showing showing depends on last add cart items.

Suppose, you want to add Crosssellsection at product detail page and want to show current product's Crosssellproducts then you need to create an extension.

On this extension, you will need to create a block which give you current product Crosssell products.

app/code/{VendorName}/{ModuleName}/Block/Crosssell.php

<?php
namespace {VendorName}\{ModuleName}\Block\Cart;

use Magento\CatalogInventory\Helper\Stock as StockHelper;
class Crosssell extends \Magento\Catalog\Block\Product\AbstractProduct
{
    protected $_maxItemCount = 4;
    protected $_checkoutSession;
    protected $_productVisibility;
    protected $stockHelper;
    protected $_coreRegistry;
    protected $_productLinkFactory;

    protected $_itemRelationsList;

    public function __construct(
        \Magento\Catalog\Block\Product\Context $context,
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Catalog\Model\Product\Visibility $productVisibility,
        \Magento\Catalog\Model\Product\LinkFactory $productLinkFactory,
        \Magento\Quote\Model\Quote\Item\RelatedProducts $itemRelationsList,
        StockHelper $stockHelper,
        array $data = []
    ) {
        $this->_checkoutSession = $checkoutSession;
        $this->_productVisibility = $productVisibility;
        $this->_productLinkFactory = $productLinkFactory;
        $this->_itemRelationsList = $itemRelationsList;
        $this->stockHelper = $stockHelper;
        parent::__construct(
            $context,
            $data
        );
        $this->_isScopePrivate = true;
        $this->_coreRegistry = $context->getRegistry();
    }

    /**
     * Get crosssell items
     *
     * @return array
     */
    public function getItems()
    {
        $items = $this->getData('items');
        if ($items === null) {
            $items = [];
            $ninProductIds = $this->_getCartProductIds();
            if ($ninProductIds) {
                $currentProduct = (int)$this->getProduct()->getId();
                if ($currentProduct) {
                    $collection = $this->_getCollection()->addProductFilter($currentProduct);
                    if (!empty($ninProductIds)) {
                        $collection->addExcludeProductFilter($ninProductIds);
                    }
                    $collection->setPositionOrder()->load();

                    foreach ($collection as $item) {
                        $ninProductIds[] = $item->getId();
                        $items[] = $item;
                    }
                }

                if (count($items) < $this->_maxItemCount) {
                    $filterProductIds = array_merge(
                        $this->_getCartProductIds(),
                        $this->_itemRelationsList->getRelatedProductIds($this->getQuote()->getAllItems())
                    );
                    $collection = $this->_getCollection()->addProductFilter(
                        $filterProductIds
                    )->addExcludeProductFilter(
                        $ninProductIds
                    )->setPageSize(
                        $this->_maxItemCount - count($items)
                    )->setGroupBy()->setPositionOrder()->load();
                    foreach ($collection as $item) {
                        $items[] = $item;
                    }
                }
            }

            $this->setData('items', $items);
        }
        return $items;
    }

    /**
     * Count items
     *
     * @return int
     * @codeCoverageIgnore
     */
    public function getItemCount()
    {
        return count($this->getItems());
    }

    public function getProduct()
    {
        return $this->_coreRegistry->registry('product');
    }
    protected function _getCartProductIds()
    {
        $ids = $this->getData('_cart_product_ids');
        if ($ids === null) {
            $ids = [];
            foreach ($this->getQuote()->getAllItems() as $item) {
                $product = $item->getProduct();
                if ($product) {
                    $ids[] = $product->getId();
                }
            }
            $this->setData('_cart_product_ids', $ids);
        }
        return $ids;
    }

    protected function _getLastAddedProductId()
    {
        return $this->_checkoutSession->getLastAddedProductId(true);
    }

    /**
     * Get quote instance
     *
     * @return \Magento\Quote\Model\Quote
     * @codeCoverageIgnore
     */
    public function getQuote()
    {
        return $this->_checkoutSession->getQuote();
    }

    /**
     * Get crosssell products collection
     *
     * @return \Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection
     */
    protected function _getCollection()
    {
        /** @var \Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection $collection */
        $collection = $this->_productLinkFactory->create()->useCrossSellLinks()->getProductCollection()->setStoreId(
            $this->_storeManager->getStore()->getId()
        )->addStoreFilter()->setPageSize(
            $this->_maxItemCount
        )->setVisibility(
            $this->_productVisibility->getVisibleInCatalogIds()
        );
        $this->_addProductAttributesAndPrices($collection);

        return $collection;
    }
    protected function _toHtml()
    {
        /* if product is out stock then render html  */
        if (!$this->getProduct()->isSaleable()) {
            return '';
        }
        return parent::_toHtml();
    }
}