1

My theme view.xml has:

<image id="product_small_image" type="small_image">
   <width>135</width>
   <height>135</height>
</image>

I have a class like this:

<?php

use Magento\Catalog\Helper\Image;

class ImageFinder
{
    private $imageHelper;

    /**
     * ImageFinder constructor.
     *
     * @param Image $imageHelper
     */
    public function __construct(
        Image $imageHelper
    ) {
        $this->imageHelper = $imageHelper;
    }

    public function getImageViaHelper($product)
    {
        return $this->imageHelper
            ->init($product, 'product_small_image')
            ->setImageFile($product->getData('small_image'))
            ->getUrl();
    }
}

which I call via:

$imagePath = $this->imageFinder->getImageViaHelper($product);

What I want is to fetch the URL of the cached product_small_image in a 135px square. However it doesn't work - it returns the original size.

If I add ->resize(135, 135) before ->getUrl() this works, but I don't want this because that will cache a new image which will not persist after flushing the media catalog cache. Can I not request a specific size which is either loaded from the cache or added to the cache when I request it?

0

Is this code running on the frontend? If not and it's Admin / CLI / cron, try using \Magento\Store\Model\App\Emulation to emulate being on the store.

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

//Run code to get image here...

$this->appEmulation->stopEnvironmentEmulation();

I've also done an alternative approach using the \Magento\Catalog\Block\Product\View\Gallery to give me the image url, for a product export script. It was run via cron, so it was wrapped in emulation above.

<?php

use Magento\Framework\UrlInterface;
use Magento\Framework\View\Element\BlockFactory;
use Magento\Catalog\Block\Product\View\Gallery;
use Magento\Catalog\Model\Product;

class ImageFinder
{
    /** @var Gallery $galleryBlock */
    private $galleryBlock;

    /** @var BlockFactory $blockFactory */
    private $blockFactory;

    /**
     * @param BlockFactory $blockFactory
     */
    public function __construct(
        BlockFactory $blockFactory
    ) {
        $this->blockFactory       = $blockFactory;
    }

    /**
     * Gets the main image for a product
     *
     * @param Product $product
     *
     * @return string
     */
    public function getProductImageUrl($product)
    {
        $galleryBlock = $this->getGalleryBlock();
        $galleryBlock->setData('product', $product);
        $productImageUrl = '';
        
        if ($product->getImage() && $product->getImage() !== 'no_selection') {
            $productImage = $galleryBlock->getImage($product, 'product_small_image');
            $productImageUrl = $productImage->getImageUrl();
        }

        return $productImageUrl;
    }
    
    /**
     * Gets a Gallery Block for use with gallery image url generation
     *
     * @return Gallery
     */
    private function getGalleryBlock()
    {
        if ($this->galleryBlock === null) {
            $config = [
                'small_image' => [
                    'image_id' => 'product_page_image_small',
                    'data_object_key' => 'small_image_url',
                    'json_object_key' => 'thumb'
                ],
                'medium_image' => [
                    'image_id' => 'product_page_image_medium',
                    'data_object_key' => 'medium_image_url',
                    'json_object_key' => 'img'
                ],
                'large_image' => [
                    'image_id' => 'product_page_image_large',
                    'data_object_key' => 'large_image_url',
                    'json_object_key' => 'full'
                ]
            ];

            $this->galleryBlock = $this->blockFactory->createBlock(
                Gallery::class,
                [
                    'galleryImagesConfig' => $config
                ]
            );
        }

        return $this->galleryBlock;
    }
}

A note on this though:

The image may not actually get generated by this approach, as it wasn't a requirement for my script. The URL was correct though, as the images existed with that URL once the cached version at that size was created by visiting the page it's actually on in the frontend. I suspect there may be a flag to set on the block to make it actually generate the image, but I haven't tried it.

Hope this helps!

2
  • Thanks for this. Yes, it's a script run via CLI or cron. In fact we already had appEmulation in place - but without the force = true param. After adding this the correct sized image is cached, and I can fetch the path. – strangerpixel Sep 4 '20 at 9:02
  • Cool, glad i could help! – Gareth James Sep 4 '20 at 9: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.