23

This is my observer:

public function execute(\Magento\Framework\Event\Observer $observer)
{
    $orderIds = $observer->getEvent()->getOrderIds();
    $order = $this->_orderRepositoryInterface->get($orderIds[0]);
    $items =$order->getAllVisibleItems();
    $productQuantity = array();
    $productPrice = array();
    $productName = array();
    $productIds = array();
    foreach($items as $item) {
        $productIds[]= $item->getProductId();
        $productName[]= $item->getSku(); 
        $productPrice[] = $item->getPrice();
        $productQuantity[]= floor($item->getQtyOrdered());
    }
}

How can I get the product image and product URL from the item?

2
  • Which event you catched? Sep 19, 2016 at 12:41
  • checkout_onepage_controller_success_action Sep 19, 2016 at 12:46

11 Answers 11

32

This way may not the best way to get a product image.

Inject \Magento\Catalog\Api\ProductRepositoryInterfaceFactory in the constructor.

protected $_productRepositoryFactory;

public function __construct(
 \Magento\Catalog\Api\ProductRepositoryInterfaceFactory $productRepositoryFactory
) {            
    $this->_productRepositoryFactory = $productRepositoryFactory;
}

We can get the image:

$product = $this->_productRepositoryFactory->create()
    ->getById($item->getProductId());
$product->getData('image');
$product->getData('thumbnail');
$product->getData('small_image');
7
  • your answer is right but what shoild i do if i have more than one product in cart how can i show more than one product image Sep 20, 2016 at 4:17
  • ok i got it @khoa. if i have more than one produc image. thanks alot Sep 20, 2016 at 4:22
  • This is not working. Value returned is some kind of string like this "/w/s/wsh10-orange_main.jpg"
    – 0xh8h
    Oct 17, 2016 at 1:37
  • 3
    @piavgh it's the path to image: pub/media/catalog/product Oct 17, 2016 at 2:17
  • 1
    so how do i use /w/s/wsh10-orange_main.jpg in <img src="" /> attribute so i can load the actual image Nov 8, 2017 at 11:06
32

If you need to return a product URL it should look like this:

//todo get product object $product 

$objectManager =\Magento\Framework\App\ObjectManager::getInstance();
$helperImport = $objectManager->get('\Magento\Catalog\Helper\Image');

$imageUrl = $helperImport->init($product, 'product_page_image_small')
                ->setImageFile($product->getSmallImage()) // image,small_image,thumbnail
                ->resize(380)
                ->getUrl();
echo $imageUrl;
3
  • Best, simple answer
    – AKKAweb
    Aug 4, 2020 at 22:19
  • This answer is exactly what am I looking for. Thanks
    – huykon225
    Oct 19, 2020 at 13:52
  • 3
    You should not resize like that, but do more definition in the view.xml of your theme, and use its id as the second parameter of the helper: The way you do it, if you delete the catalog/product/cache directory, and ask for your "380" image directly in browser, Magento will not regenerate it automatically: he is not aware that this format exists and won't do so. Feb 9, 2021 at 9:18
25

If you want the published/cache frontend URL of an image for a specific store view (like I did) this is working for me:

/**
 * @var \Magento\Store\Model\App\Emulation
 */
protected $appEmulation;

/**
 * @var \Magento\Store\Model\StoreManagerInterface
 */
protected $storeManager;

/**
 * @var \Magento\Catalog\Api\ProductRepositoryInterfaceFactory
 */
protected $productRepositoryFactory;

/**
 * @var \Magento\Catalog\Helper\ImageFactory
 */
protected $imageHelperFactory;

/**
 * @param \Magento\Store\Model\StoreManagerInterface $storeManager
 * @param \Magento\Store\Model\App\Emulation $appEmulation
 * @param \Magento\Catalog\Api\ProductRepositoryInterfaceFactory $productRepositoryFactory
 * @param \Magento\Catalog\Helper\ImageFactory $helperFactory
 */
public function __construct(
    \Magento\Store\Model\StoreManagerInterface $storeManager,
    \Magento\Store\Model\App\Emulation $appEmulation,
    \Magento\Catalog\Api\ProductRepositoryInterfaceFactory $productRepositoryFactory,
    \Magento\Catalog\Helper\ImageFactory $imageHelperFactory
)
{
    $this->storeManager = $storeManager;
    $this->appEmulation = $appEmulation;
    $this->productRepositoryFactory = $productRepositoryFactory;
    $this->imageHelperFactory = $imageHelperFactory;
}

Then, wherever you need to get the image frontend URL:

$sku = "my-sku";
// get the store ID from somewhere (maybe a specific store?)
$storeId = $this->storeManager->getStore()->getId();
// emulate the frontend environment
$this->appEmulation->startEnvironmentEmulation($storeId, \Magento\Framework\App\Area::AREA_FRONTEND, true);
// load the product however you want
$product = $this->productRepositoryFactory->create()->get($sku);
// now the image helper will get the correct URL with the frontend environment emulated
$imageUrl = $this->imageHelperFactory->create()
  ->init($product, 'product_thumbnail_image')->getUrl();
// end emulation
$this->appEmulation->stopEnvironmentEmulation();

You can select other images types besides product_thumbnail_image: see magento/theme-frontend-luma/etc/view.xml for a list of available product images, or create your own in a view.xml file.

2
  • 2
    WTF? that is just sick :D Nov 2, 2017 at 9:13
  • Just tried this solution and I'm not getting any errors, though the returned URL doesn't exist and the string is empty. I've tried with 'product_base_image', 'product_small_image' and 'product_thumbnail_image', none of which work. Can you advise please? Or is there an efficient way to do this using the product repository? As I am already loading that elsewhere in my block.
    – Muckee
    Apr 24, 2018 at 15:57
7

That's the way I did. it's quite efficient and clean:

1) First, you need to inject the following classes:

protected $_storeManager;
protected $_appEmulation;
protected $_blockFactory;

public function __construct(
    ...
    \Magento\Store\Model\StoreManagerInterface $storeManager,
    \Magento\Framework\View\Element\BlockFactory $blockFactory,
    \Magento\Store\Model\App\Emulation $appEmulation)
{
    $this->_storeManager = $storeManager;
    $this->_blockFactory = $blockFactory;
    $this->_appEmulation = $appEmulation;
}

2) Then, create a getImageUrl method with the code below:

protected function getImageUrl($product, string $imageType = '')
{
    $storeId = $this->_storeManager->getStore()->getId();

    $this->_appEmulation->startEnvironmentEmulation($storeId, \Magento\Framework\App\Area::AREA_FRONTEND, true);

    $imageBlock =  $this->_blockFactory->createBlock('Magento\Catalog\Block\Product\ListProduct');
    $productImage = $imageBlock->getImage($product, $imageType);
    $imageUrl = $productImage->getImageUrl();

    $this->_appEmulation->stopEnvironmentEmulation();

    return $imageUrl;
}

Note: The "appEmulation" code is only necessary when you making this call from the admin or for an API. Otherwise, you will get the error below (or similar):

Unable to resolve the source file for 'webapi_rest/_view/en_AU/Magento_Catalog/images/product/placeholder/.jpg'

3) Call the getImageUrl passing the product object and the type of image you want (based on your view.xml file)

...
$smallImage = $this->getImageUrl($productObject, 'product_page_image_small');
...
3

For gettting custom image url I used this code. So if the image does not exits it will load the default theme image.

$product = $block->getProduct();

$productImageAttr = $product->getCustomAttribute('product_banner_image');

if ($productImageAttr && $productImageAttr->getValue() != 'no_selection') {

    $productImage = $this->helper('Magento\Catalog\Helper\Image')
    ->init($product, 'product_banner_image')
    ->setImageFile($productImageAttr->getValue());

    $imageUrl = $productImage->getUrl();

} else {

    $imageUrl = $this->getViewFileUrl('images/cat-img1.jpg'); // Theme/web/images

}
1
  • This isn't get the full cache path image. Ex: domain.com/media/catalog/product/cache/{cache_id}/w/j/wj23.jpg
    – fudu
    May 20, 2021 at 3:03
1

You Can direct use this on .phtml

$this->helper('Magento\Cms\Helper\Wysiwyg\Images')
->getBaseUrl().'catalog/product'.$_product->getImage();
1
  • This isn't get the full cache path image. Ex: domain.com/media/catalog/product/cache/{cache_id}/w/j/wj23.jpg
    – fudu
    May 20, 2021 at 3:01
1

My way works with watermarks and is same as magento using.

DI:

/** @var \Magento\Catalog\Block\Product\ImageBuilder */
private $imageBuilder;

Method returns string (placeholder):

private function getProductImageUrl(Product $product): string
{
    $image = $this->imageBuilder
        ->setProduct($product)
        ->setImageId('product_small_image')
        ->setAttributes([])
        ->create();

    return $image->getImageUrl();
}

Method returns null or string:

private function getProductImageUrlOrNull(Product $product): ?string
{
    if (empty($product->getImage()) || $product->getImage() === SitemapResourceProduct::NOT_SELECTED_IMAGE) {
        return null;
    }

    return $this->getProductImageUrl($product);
}
2
  • This is successfully in get the full cache path image, but this code is created it's own cache_id. Ex: domain.com/media/catalog/product/cache/{cache_id}/w/j/wj23.jpg
    – fudu
    May 20, 2021 at 3:00
  • Actually, the cache_id is depend on what is your image_id, in my case, i transfer setImageId("product_page_image_medium") instead of setImageId('product_small_image'), and that solved my problem. You can check other image_id at magento/theme-frontend-luma/etc/view.xml
    – fudu
    May 20, 2021 at 4:17
1

In multi-store mode and using store view code in the URL's. You can get the product's full image URL using this method:

$productId  = 12; //eg;
$productFactory = $objectManager->create('\Magento\Catalog\Model\ProductFactory');                            
$product        = $productFactory->create()->load($productId);
$attribute      = $product->getResource()->getAttribute('image');
$imageUrl       = $attribute->getFrontend()->getUrl($product);
1
  • This isn't get the full cache path image. Ex: domain.com/media/catalog/product/cache/{cache_id}/w/j/wj23.jpg
    – fudu
    May 20, 2021 at 2:46
1

Since this seems to be the top search results and none of the answers really worked for me, here's a simple helper class to get an product's thumbnail image from the cache:

<?php

namespace Mobweb\Core\Helper;

use Magento\Framework\App\Helper\Context;
use Magento\Catalog\Helper\Image as ImageHelper;

class Product extends \Magento\Framework\App\Helper\AbstractHelper
{
    /** @var ImageHelper */
    private $imageHelper;

    /**
     * @param ImageHelper $imageHelper
     * @param Context $context
     */
    public function __construct(
        ImageHelper $imageHelper,
        Context $context
    )
    {
        $this->imageHelper = $imageHelper;

        parent::__construct($context);
    }

    /**
     * @param \Magento\Catalog\Model\Product $product
     */
    public function getImageUrl(\Magento\Catalog\Model\Product $product)
    {
        return $this->imageHelper->init($product, 'product_thumbnail_image')->getUrl();
    }
}
1

To get the cached image url:

Construct

/** 
 * @var \Magento\Catalog\Helper\Image 
 */
private $imageHelper;

/**
 * @var \Magento\Store\Model\App\Emulation
 */
protected $appEmulation;

/**
 * Constructor.
 * @param \Magento\Catalog\Helper\Image $imageHelper
 * @param \Magento\Store\Model\App\Emulation $appEmulation
 */
public function __construct(
    \Magento\Catalog\Helper\Image $imageHelper,
    \Magento\Store\Model\App\Emulation $appEmulation
){
    $this->imageHelper = $imageHelper;
    $this->appEmulation = $appEmulation;
}

Get an image

public function getBaseImageUrl(ProductInterface $product, $storeId)
{
    $this->appEmulation->startEnvironmentEmulation($storeId, \Magento\Framework\App\Area::AREA_FRONTEND, true);

    // 'product_base_image' or any image code from vendor\magento\theme-frontend-luma\etc\view.xml
    $url = $this->imageHelper->init($product, 'product_base_image')->getUrl();

    $this->appEmulation->stopEnvironmentEmulation();

    return $url;
}

Get all images

public function getBaseImageUrl(ProductInterface $product, $storeId)
{
    $this->appEmulation->startEnvironmentEmulation($storeId, \Magento\Framework\App\Area::AREA_FRONTEND, true);

    $urls = [];
    foreach($product->getMediaGalleryEntries() as $image){
        // 'product_base_image' or any image code from vendor\magento\theme-frontend-luma\etc\view.xml
        $baseImage = $this->imageHelper->init($product, 'product_base_image')
                        ->setImageFile($image->getFile())
                        ->getUrl();

        $urls[] = $baseImage;
    }

    $this->appEmulation->stopEnvironmentEmulation();

    return $urls;
}
1
  • I couldn't get the first (single) getUrl() function to give me a result (it always returned the placeholder as image for this product.) I used a combination of the two examples (single/multiple) to get an image for me: $this->imageHelper->init($product, $imageIdString)->setImageFile($product->getImage())->getUrl(); May 31 at 13:30
0

The simplest way to get base image,

$store = $objectManager->get('Magento\Store\Model\StoreManagerInterface')->getStore();
$imageUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $product->getImage();
1
  • This isn't get the full cache path image. Ex: domain.com/media/catalog/product/cache/{cache_id}/w/j/wj23.jpg
    – fudu
    May 20, 2021 at 2:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.