Bhaveshpp

Professional Magento Developr - Healp eachother to grow

Magento2: Custom product listing

20 Aug 2021 » magento2

app\design\frontend\MageBig\martfury\child\Magento_Catalog\templates\product\view\addtocart.phtml

<?php if (!$isAvailable) :?>
    <?=$this->getLayout()->createBlock("Bhaveshpp\Custom\Block\RelatedProduct")->setProduct($_product)->setTemplate("Bhaveshpp_Custom::product/related/list.phtml")->toHtml()?>
<?php endif; ?> 

\app\code\Bhaveshpp\Custom\view\frontend\templates\product\related\list.phtml

/**
 * Product list template
 *
 * @var $block \Bhaveshpp\Custom\Block\RelatedProduct
 * @var \Magento\Framework\Escaper $escaper
 * @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer
 */
use Magento\Framework\App\Action\Action;
$relatedProducts = $block->getProduct()->getRelatedProducts();
$_helper = $block->getData('outputHelper');
$imageDisplayArea = 'category_page_grid';
$count = 0;
if (count($relatedProducts)>0) :?>
<div id="related-products">
    <h3 class="title"><?= /* @escapeNotVerified */ __("Alternatívy k tomuto produktu")?></h3>
    <div class="product-items">
    <?php foreach ($relatedProducts as $key => $relatedProduct) : $_product = $block->loadProduct($relatedProduct);?>
        <?php if($count == 4) break;?>
        <?php
        $productImage = $block->getImage($_product, $imageDisplayArea);
        ?>
        <div class="product-item">
            <div class="image">
                <a href="<?= $escaper->escapeUrl($_product->getProductUrl()) ?>"
                class="product photo product-item-photo"
                tabindex="-1">
                    <?= $productImage->toHtml() ?>
                </a>
            </div>
            <div class="detail">
                <strong class="product name product-item-name">
                    <a class="product-item-link"
                    href="<?= $escaper->escapeUrl($_product->getProductUrl()) ?>">
                        <?=/* @noEscape */ $_helper->productAttribute($_product, $_product->getName(), 'name')?>
                    </a>
                </strong>
                <?= /* @noEscape */ $block->getProductPrice($_product) ?>
                <div class="actions-primary">
                    <?php if ($_product->isSaleable()):?>
                        <?php $postParams = $block->getAddToCartPostParams($_product); ?>
                        <form data-role="tocart-form"
                                data-product-sku="<?= $escaper->escapeHtml($_product->getSku()) ?>"
                                action="<?= $escaper->escapeUrl($postParams['action']) ?>"
                                method="post">
                            <input type="hidden"
                                    name="product"
                                    value="<?= /* @noEscape */ $postParams['data']['product'] ?>">
                            <input type="hidden"
                                    name="<?= /* @noEscape */ Action::PARAM_NAME_URL_ENCODED ?>"
                                    value="<?=
                                    /* @noEscape */ $postParams['data'][Action::PARAM_NAME_URL_ENCODED]
                                    ?>">
                            <?= $block->getBlockHtml('formkey') ?>
                            <button type="submit"
                                    title="<?= $escaper->escapeHtmlAttr(__('Add to Cart')) ?>"
                                    class="action tocart primary">
                                <span><?= $escaper->escapeHtml(__('Add to Cart')) ?></span>
                            </button>
                        </form>
                    <?php else:?>
                        <?php if ($_product->isAvailable()):?>
                            <div class="stock available">
                                <span><?= $escaper->escapeHtml(__('In stock')) ?></span></div>
                        <?php else:?>
                            <div class="stock unavailable">
                                <span><?= $escaper->escapeHtml(__('Out of stock')) ?></span></div>
                        <?php endif; ?>
                    <?php endif; ?>
                </div>
            </div>
        </div>
    <?php $count++; endforeach;?>
    </div>
<?php endif;?>

\app\code\Bhaveshpp\Custom\Block\RelatedProduct.php

namespace Bhaveshpp\Custom\Block;

use Magento\Catalog\Helper\Output as OutputHelper;
use Magento\Framework\App\ActionInterface;
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\Url\Helper\Data;
use Magento\Catalog\Model\Product;
use Magento\Framework\App\ObjectManager;
use Magento\Catalog\Pricing\Price\FinalPrice;
use Magento\Framework\Pricing\Render;

class RelatedProduct extends \Magento\Catalog\Block\Product\AbstractProduct
{

    /**
     * @var Product
     */
    public $product;
    
    /**
     * @var Product
     */
    public $relatedProduct;
    
    /**
     * @var ProductRepository
     */
    public $productRepository;
    
    /**
     * initalize
     *
     * @param Context $context
     * @param ProductRepositoryInterface $productRepository
     * @param Data $urlHelper
     * @param array $data
     * @param OutputHelper|null $outputHelper
     */
    public function __construct(
        Context $context,
        ProductRepositoryInterface $productRepository,
        Data $urlHelper,
        array $data = [],
        ?OutputHelper $outputHelper = null
    )
    {
        $this->urlHelper = $urlHelper;
        $this->productRepository = $productRepository;
        $data['outputHelper'] = $outputHelper ?? ObjectManager::getInstance()->get(OutputHelper::class);
        parent::__construct(
            $context,
            $data
        );
    }
    
    /**
     * Set parent product
     *
     * @param Product $product
     * @return object
     */
    public function setProduct($product)
    {
        $this->product = $product;
        return $this;
    }

    /**
     * Get Product data in template
     *
     * @return object
     */
    public function getProduct()
    {
        return $this->product;
    }
    /**
     * Load product by sku
     *
     * @param Product $product
     * @return object
     */
    public function loadProduct($product)
    {
        $this->relatedProduct = $this->productRepository->getById($product->getEntityId());
        return $this->relatedProduct;
    }

    /**
     * Get product price.
     *
     * @param Product $product
     * @return string
     */
    public function getProductPrice(Product $product)
    {
        $priceRender = $this->getPriceRender();

        $price = '';
        if ($priceRender) {
            $price = $priceRender->render(
                FinalPrice::PRICE_CODE,
                $product,
                [
                    'include_container' => true,
                    'display_minimal_price' => true,
                    'zone' => Render::ZONE_ITEM_LIST,
                    'list_category_page' => true
                ]
            );
        }

        return $price;
    }

    /**
     * Specifies that price rendering should be done for the list of products.
     * (rendering happens in the scope of product list, but not single product)
     *
     * @return Render
     */
    protected function getPriceRender()
    {
        return $this->getLayout()->getBlock('product.price.render.default')
            ->setData('is_product_list', true);
    }


    /**
     * Get post parameters
     *
     * @param Product $product
     * @return array
     */
    public function getAddToCartPostParams(Product $product)
    {
        $url = $this->getAddToCartUrl($product, ['_escape' => false]);
        return [
            'action' => $url,
            'data' => [
                'product' => (int) $product->getEntityId(),
                ActionInterface::PARAM_NAME_URL_ENCODED => $this->urlHelper->getEncodedUrl($url),
            ]
        ];
    }

}