How to get product image and URL in Magento 2?
-
15-04-2021 - |
質問
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?
解決
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');
他のヒント
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);