Question

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?

Était-ce utile?

La solution

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');

Autres conseils

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;

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.

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');
...

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

}

You Can direct use this on .phtml

$this->helper('Magento\Cms\Helper\Wysiwyg\Images')
->getBaseUrl().'catalog/product'.$_product->getImage();

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);
}

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();

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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à magento.stackexchange
scroll top