26

I'm trying to create a static block for showing dynamic products. This is code that is supposed to get every child category and print the image for each product in each category.

<?php
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
    $category = $objectManager->get('Magento\Framework\Registry')->registry('current_category');
    ?><ol><?php
    foreach ($category->getChildrenCategories() as $child_category) {
        ?><li>
            <ul><?php
                foreach ($child_category->getProductCollection() as $product) {
                    ?><li><img src="<?php echo $product->getImage();?>"/><li><?php
                }
            ?></ul>
        </li><?php
    }
    ?></ol>

It is almost working except for the img srcs are only "/a/b/ab001.jpg" as an example and not the full path e.g. "/pub/media/catalog/product/cache/1/small_image/240x300/abc123def456/a/b/001.jpg" so the images cannot be found. What is the correct way of getting product images?

1
  • 1
    Don't try to use Object Manager directly on your template. We should create new block or re-use exist functions. Jun 4, 2016 at 10:14

13 Answers 13

39

If your block extends Magento\Catalog\Block\Product\AbstractProduct, you can use:

$imageType = 'category_page_list'; // choose which image
$image = $block->getImage($product, $imageType);

Then either get the image URL with

$image->getImageUrl();

or if you want to output it as <img> element:

echo $image->toHtml();

If your block does not / cannot extend the abstract product block, you can create a getImage() method on your own:

public function getImage($product, $imageId)
{
    return $this->imageBuilder->setProduct($product)
        ->setImageId($imageId)
        ->create();
}

$this->imageBuilder has to be injected as Magento\Catalog\Block\Product\ImageBuilder


The $imageType or $imageId variables should be one of the image types defined in the theme, for example category_page_list.

See app/design/frontend/Magento/luma/etc/view.xml for all image types in the Luma theme, for example.

In Magento 2 these image types are used instead of defining width and height directly in the template.

11
  • I am trying your code but i am getting this error Uncaught Magento\Framework\View\Asset\File\NotFoundException: Unable to resolve the source file for 'adminhtml/_view/en_US/Magento_Catalog/images/product/placeholder/.jpg'
    – ND17
    Sep 9, 2016 at 9:18
  • @ND17 two questions: 1) are you using the block in the admin area? This code is intended for frontend only 2) do you have configured a placeholder image? If not and a product has no image, you'll always get errors Sep 9, 2016 at 9:25
  • 1
    @davideghz one of the image types defined in the theme, for example category_page_list. See: github.com/magento/magento2/blob/… in Magento 2 you use these instead of defining width and height directly in the template Jan 4, 2017 at 12:33
  • 4
    Any idea of why it would bring back the placeholder instead of the assigned image?
    – Laura
    Feb 28, 2017 at 22:36
  • 3
    I am having the same problem as @Laura. It always returns the placeholder image instead of the assigned image (the assigned image is perfectly visible in the product list or generic product details page otherwise).
    – fritzmg
    Jul 24, 2018 at 11:07
9

If you need to resize the product image and use the default Magento image cache system and you are not in the frontend area, you can use this workaround.

Use case : It may be useful if you need image URLs resized on your custom API for an external application.

Function code :

/**
 * @var \Magento\Catalog\Model\ProductFactory
 */
protected $productFactory;

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

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

/**
 * Constructor.
 *
 * @param \Magento\Catalog\Model\ProductFactory $productFactory
 * @param \Magento\Store\Model\App\Emulation $appEmulation
 * @param \Magento\Catalog\Helper\ImageFactory $helperFactory
 * @param \Magento\Store\Model\StoreManagerInterface $storeManager
 */
public function __construct(
    \Magento\Catalog\Model\ProductFactory $productFactory,
    \Magento\Store\Model\App\Emulation $appEmulation,
    \Magento\Catalog\Helper\ImageFactory $helperFactory,
    \Magento\Store\Model\StoreManagerInterface $storeManager,
) {
    $this->productFactory                   = $productFactory;
    $this->imageBuilder                     = $imageBuilder;
    $this->helperFactory                    = $helperFactory;
    $this->appEmulation                     = $appEmulation;
    $this->storeManager                     = $storeManager;
}

/**
 * Retrieve product image
 *
 * @param \Magento\Catalog\Model\Product $product
 * @param string $imageId
 * @param array $attributes
 * @return \Magento\Catalog\Block\Product\Image
 */
public function getImage($product, $imageId, $attributes = [])
{
    $image = $this->helperFactory->create()->init($product, $imageId)
        ->constrainOnly(true)
        ->keepAspectRatio(true)
        ->keepTransparency(true)
        ->keepFrame(false)
        ->resize(200, 300);

    return $image;
}

public function customFunction()
{
    // some stuff here

    $storeId = $this->storeManager->getStore()->getId();

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

    $product = $this->productFactory->create()->loadByAttribute('sku', 'productSKU');
    $imageUrl = $this->getImage($product, 'product_base_image')->getUrl();

    echo $imageUrl;

    $this->appEmulation->stopEnvironmentEmulation();

    // some stuff here
}

The output example :

http://{domain}/media/catalog/product/cache/1/image/200x300/e9c3970ab036de70892d86c6d221abfe/s/r/{imageName}.jpg

Comments :

The third parameter of the function startEnvironmentEmulation is used to force the use of frontend area if you are already on the same storeId. (usefull for API area)

This workaround avoid you to have this kind of errors :

http://XXXX.com/pub/static/webapi_rest/_view/en_US/Magento_Catalog/images/product/placeholder/.jpg

Uncaught Magento\Framework\View\Asset\File\NotFoundException: Unable to resolve the source file for 'adminhtml/_view/en_US/Magento_Catalog/images/product/placeh‌​older/.jpg'
2
  • 1
    Thanks for the tip on the environment emulation, just what I needed.
    – thaddeusmt
    Mar 16, 2017 at 21:33
  • 2
    The environment emulation saved my day. Many thanks!
    – medina
    Jun 14, 2017 at 0:23
8

Try it

$store = $objectManager->get('Magento\Store\Model\StoreManagerInterface')->getStore();
$imageUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $product->getImage();
1
  • 1
    This one is good because it will automatically give the secure / insecure URL according to the current request Nov 2, 2017 at 19:29
4

Try This code..

$ProductImageUrl = $block->getUrl('pub/media/catalog').'product'.$_product->getImage();
4
  • Welcome to Magento SE. Answers that only contain one line of code are often not very helpful. In this case it's relatively clear how this line is supposed to be used, but using getUrl() is not the right way even if it may work accidentally. It takes a $route parameter in the form "module/controller/action". "pub/media/catalog" looks like a route, but is not. Jul 12, 2016 at 7:39
  • Doesn't use the object manager, good answer. Even if only one line. Jul 25, 2016 at 9:13
  • @LM_Fielding Not every answer that doesn't use the object manager is automatically good. Sep 16, 2016 at 7:33
  • Try this code and post your comment Mar 1, 2017 at 11:54
2

You can use ObjectManager or Block.

Objectmanager :

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$store = $objectManager->get('Magento\Store\Model\StoreManagerInterface')->getStore();
$imageUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $product->getImage();

Block :

protected $_storeManagerInterface;

public function __construct(
  ...
  \Magento\Store\Model\StoreManagerInterface $storeManagerInterface,
  ...
)
{
  ...
  $this->_storeManagerInterface = $storeManagerInterface;
  ...
}

...

public function getStoreInterface($imgUrl){
   $store = $this->_storeManagerInterface->getStore();
   $storeMedia = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $imgUrl;
   return $storeMedia;
}
...

Call the function :

<img src="<?php echo $block->getStoreInterface($imgUrl) ?>"/>
1

Maybe Magento\Catalog\Helper\Product::getImageUrl() could help. I don't understand why Magento developers didn't implement it in Magento\Catalog\Helper\Image class since the getUrl method in image helper does not return what one could expect...

1

Please try this code:

$prdId = 35;
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$hotPrd = $objectManager->get('Magento\Catalog\Model\Product')->load($prdId);
$store = $objectManager->get('Magento\Store\Model\StoreManagerInterface')->getStore();
echo $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $hotPrd->getThumbnail();
0

Try this code

<img class="test-image" alt="image" src="<?php echo $block->getUrl('pub/media/catalog/product', ['_secure' => $block->getRequest()->isSecure()]).$product->getImage();?>" />

Hope this will help you

2
0

In your module:

public function getProducts()
{
    //... create collection code goes here...

    $result = [ ];

    foreach ( $collection as $product ) {
        $result[] = [
            'id'        => $product->getId(),
            '_sku'      => $product->getSku(),
            'permalink' => $product->getProductUrl($product),
            'title'     => $product->getName(),
            'raw_price' => $product->getPrice(),
            'image_url' => $this->getUrl().'pub/media/catalog/product'.$product->getImage()
        ];
    }

    return $result;
}

Then in your block you'll get this result:

print_r($block->getProducts());

Well, it's not perfect, but it works for me.

Take a look at result: enter image description here

0

In your class inject dependency StoreManagerInterface like:

use \Magento\Framework\View\Element\Template\Context;
use \Magento\Store\Model\StoreManagerInterface;

public function __construct(Context $context, StoreManagerInterfac $storeManager)
    {
        parent::__construct($context);
        $this->_storeManager = $storeManager;

    }

after in your method, for obtain thumbail for example

public function getProductThumbnail(){

        return $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $product->getImage();
    }
0

You can try this below code.

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$category = $objectManager->get('Magento\Framework\Registry')->registry('current_category');
$childcategories = $category->getChildrenCategories();

foreach($childcategories as $child)
    {
echo '<li class="sub-cat">';
        $cat = $objectManager->create('Magento\Catalog\Model\Category')->load($child->getId()); 
        ?>
        <a href="<?php echo $cat->getUrl(); ?>">
        <div class="sub-title">
            <h3><?php echo $cat->getName();?></h3>
        </div> 
    <?php
        if ($_imgUrl = $cat->getImageUrl())
        {
            $_imgHtml = '<div class="category-image"><img src="' . $_imgUrl . '" alt="' . $block->escapeHtml($cat->getName()) . '" title="' . $block->escapeHtml($cat->getName()) . '" class="image" /></div>';
            $_imgHtml = $_helper->categoryAttribute($cat, $_imgHtml, 'image');
            /* @escapeNotVerified */ echo $_imgHtml;
        }  

    ?>      
    <?php echo '</a></li>'; }
    echo '</ul>';
}
0

This is another working method:

/** @var \Magento\Framework\UrlInterface $urlManager */
$url = $urlManager->getDirectUrl('pub/media/catalog/product' . $product->getImage());

Or respecting secure / insecure URL based on current request:

/** @var \Magento\Framework\UrlInterface $urlManager */
/** @var \Magento\Framework\App\RequestInterface $request */
$url = $urlManager->getDirectUrl(
    'pub/media/catalog/product' . $product->getImage(),
    ['_secure' => $request->isSecure()]
);

I'll leave the object instantiation to your own imagination.

0

We can get Base Image url in phtml file

$_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$imageHelper  = $_objectManager->get('\Magento\Catalog\Helper\Image');
<?php $image_url = $imageHelper->init($product, 'product_base_image')->setImageFile($product->getFile())->resize($imagewidth, $imageheight)->getUrl(); ?>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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