23

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
    Don't try to use Object Manager directly on your template. We should create new block or re-use exist functions. – Khoa TruongDinh Jun 4 '16 at 10:14

13 Answers 13

27

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.

  • 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 '16 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 – Fabian Schmengler Sep 9 '16 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 – Fabian Schmengler Jan 4 '17 at 12:33
  • 3
    Any idea of why it would bring back the placeholder instead of the assigned image? – Laura Feb 28 '17 at 22:36
  • 2
    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 '18 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'
  • 1
    Thanks for the tip on the environment emulation, just what I needed. – thaddeusmt Mar 16 '17 at 21:33
  • 2
    The environment emulation saved my day. Many thanks! – medina Jun 14 '17 at 0:23
  • +1 for API usefulness – tony Jun 17 '18 at 10:13
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
    This one is good because it will automatically give the secure / insecure URL according to the current request – Milan Simek Nov 2 '17 at 19:29
3

Try This code..

$ProductImageUrl = $block->getUrl('pub/media/catalog').'product'.$_product->getImage();
  • 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. – Fabian Schmengler Jul 12 '16 at 7:39
  • Doesn't use the object manager, good answer. Even if only one line. – LM_Fielding Jul 25 '16 at 9:13
  • @LM_Fielding Not every answer that doesn't use the object manager is automatically good. – Fabian Schmengler Sep 16 '16 at 7:33
  • Try this code and post your comment – Shihas Suliaman Mar 1 '17 at 11:54
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();
1

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) ?>"/>
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

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, privacy policy and cookie policy

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