2

I am showing Listrak on site recommend product on my website.

Product images are very big, I need resizes images.

I have images name like 2/0/20mm.jpg and I am appeding it with https://example.com/media/catalog/product

So it will be

https://example.com/media/catalog/product/2/0/20mm.jpg

But i want

https://example.com/media/catalog/product/cache/fc6ca0131474e1299ecedb80f5002264/2/0/20mm.jpg

Note: I do not have product object, So can't load an get resized images that why need to get cache folder path so I will append image name.

Thanks in advance!

5
  • You can search magento code for the hash function which creates that hash and copy parts of it to your code
    – Alex
    Jul 24, 2020 at 18:53
  • Are you trying to access the Magento images from and external website and don't know the URL? I believe the hash part is the same for same image resize settings, so you could hardcode it
    – Alex
    Jul 24, 2020 at 19:14
  • @Alex, Yes I thought same to find hash code but could not find. at the moment I have written hard coded hash value but when I flush catalogue cache from admin, will hash value will change ?
    – Pawan
    Jul 25, 2020 at 5:00
  • I think it shouldn't change. Only when you change the image format in the theme I guess
    – Alex
    Jul 25, 2020 at 7:21
  • 1
    @Alex, Yes you are right, it is not changing hash after flush catalogue cache. we can hard code it. please add your comment as answer :)
    – Pawan
    Aug 5, 2020 at 12:18

3 Answers 3

2

You can hard code the hash as it depends only on the image target format and mostly does not change.

2

If you want to get the cache path (hash) of the small_image on PLP then you can get the following way.

  1. Need to get the size of the small_image from view.xml.
  2. Need to generate the directory hash.
  3. Generate an URL, based on the hash.

1. Step Inject this class into the constructor.

use Magento\Framework\View\ConfigInterface as ViewConfigInterface;

Then you can retrieve width and height like this. If the sizes are different in the GRID view then need to use category_page_grid instead of category_page_list. (But you can use any other id here.)

$imagesConfig =$this->viewConfig->getViewConfig()->getMediaEntities(
    'Magento_Catalog',
    'images'
);

$width = $imagesConfig['category_page_list']['width'];
$height = $imagesConfig['category_page_list']['height'];

2. step

Inject EncryptorInterface into the constructor.

use Magento\Framework\Encryption\Encryptor;
use Magento\Framework\Encryption\EncryptorInterface;

Then you need this function.

/**
 * Converting bool into a string representation
 *
 * @param array $miscParams
 * @return array
 */
private function convertToReadableFormat(array $miscParams)
{
    $miscParams['image_height'] = 'h:' . ($miscParams['image_height'] ?? 'empty');
    $miscParams['image_width'] = 'w:' . ($miscParams['image_width'] ?? 'empty');
    $miscParams['quality'] = 'q:' . ($miscParams['quality'] ?? 'empty');
    $miscParams['angle'] = 'r:' . ($miscParams['angle'] ?? 'empty');
    $miscParams['keep_aspect_ratio'] = (!empty($miscParams['keep_aspect_ratio']) ? '' : 'non') . 'proportional';
    $miscParams['keep_frame'] = (!empty($miscParams['keep_frame']) ? '' : 'no') . 'frame';
    $miscParams['keep_transparency'] = (!empty($miscParams['keep_transparency']) ? '' : 'no') . 'transparency';
    $miscParams['constrain_only'] = (!empty($miscParams['constrain_only']) ? 'do' : 'not') . 'constrainonly';
    $miscParams['background'] = !empty($miscParams['background'])
        ? 'rgb' . implode(',', $miscParams['background'])
        : 'nobackground';
    return $miscParams;
}

Finally, you can get the path like this:

$path = $this->encryptor->hash(
    implode('_', $this->convertToReadableFormat([
        'image_height' => $height,
        'image_width' => $width,
        'background' => [255, 255, 255],
        'angle' => null,
        'quality' => 80,
        'keep_aspect_ratio' => true,
        'keep_frame' => true,
        'keep_transparency' => true,
        'constrain_only' => true,
    ])),
    Encryptor::HASH_VERSION_MD5
);

3. step You can use StoreManager to get the media URL and generate the URL.

{MEDIA_URL}/catalog/product/cache/{CACHE_PATH}

1
  • I had to pass ["area"=>"frontend"] to getViewConfig() to get all formats.
    – bfontaine
    Aug 22 at 17:34
0

I've made a bash command to get the cache image file and delete it (optionally). I leave the source code below, maybe it will help someone.

In my di.xml file:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\Console\CommandList">
        <arguments>
            <argument name="commands" xsi:type="array">
                <item name="regenarate_image" xsi:type="object">Vendor\Base\Console\RegenerateImages</item>
            </argument>
        </arguments>
    </type>
</config>

and my Command:

    namespace Vendor\Base\Console;
    use Magento\Framework\App\Area;
    use Magento\Framework\App\State;
    use Symfony\Component\Console\Command\Command;
    use Symfony\Component\Console\Input\InputArgument;
    use Symfony\Component\Console\Input\InputInterface;
    use Symfony\Component\Console\Output\OutputInterface;
    use Exception;
    use Magento\Catalog\Model\View\Asset\ImageFactory;
    use Magento\Catalog\Api\ProductRepositoryInterface;
    use Magento\Framework\App\Filesystem\DirectoryList;
    use Magento\Framework\Filesystem;
    use Magento\Framework\Filesystem\Driver\File;
    use Magento\Framework\Exception\LocalizedException;
    
    class RegenerateImages extends Command
    {
        const IMAGE_ID = 'category_page_grid';
        const NAME_ARGUMENT = 'sku';
    
        /**
         * @var State
         */
        private $state;
    
        /**
         * @var ImageFactory
         */
        private $imageFactory;
    
        /**
         * @var ProductRepositoryInterface
         */
        private $productRepository;
    
        /**
         * @var Filesystem
         */
        private $filesystem;
    
        /**
         * @var File
         */
        private $file;
    
        /**
         * @param State $state
         * @param ImageFactory $imageFactory
         * @param ProductRepositoryInterface $productRepository
         * @param Filesystem $filesystem
         * @param File $file
         * @param string|null $name
         */
        public function __construct(
            State $state,
            ImageFactory $imageFactory,
            ProductRepositoryInterface $productRepository,
            Filesystem $filesystem,
            File $file,
            string $name = null
        ) {
            $this->state = $state;
            $this->imageFactory = $imageFactory;
            $this->productRepository = $productRepository;
            $this->filesystem = $filesystem;
            $this->file = $file;
    
            parent::__construct($name);
        }
    
        /**
         * @usage bin/magento vendor:regenarate_image {product sku}
         * @return void
         */
        protected function configure()
        {
            $this->setName('vendor:regenarate_image');
            $this->setDescription('Regenarate product image using the SKU');
            $this->addArgument(
                self::NAME_ARGUMENT,
                InputArgument::REQUIRED,
                'Product Sku'
            );
    
            parent::configure();
        }
    
        /**
         * @param InputInterface $input
         * @param OutputInterface $output
         * @return int|void
         * @throws LocalizedException
         */
        protected function execute(InputInterface $input, OutputInterface $output)
        {
            $this->state->setAreaCode(Area::AREA_FRONTEND);
            $sku = (string) $input->getArgument(self::NAME_ARGUMENT);
    
            try {
                $product = $this->productRepository->get($sku);
            }catch (Exception $error){
                $output->writeln("Cannot find product with SKU: {$sku} . More details". $error->getMessage());
                return;
            }
    
            $imageUrl = $this->imageFactory->create([
                'miscParams' => $this->getImageMiscParams(),
                'filePath' => $product->getData('small_image'),
            ]);
    
            try{
                $imageUrl = $imageUrl->getUrl();
            }catch (Exception $error){
                $output->writeln($error->getMessage());
                return;
            }
    
            $output->writeln("Cache Image Url: {$imageUrl} ");
    
            $afterCacheFolder = explode('cache/', $imageUrl);
            $afterCacheFolder = $afterCacheFolder[1];
            $output->writeln("Getting hash: {$afterCacheFolder} ");
    
            $mediaPath = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath();
    
            $catalogMediaImageCacheFolder = $mediaPath.'catalog/product/cache/'.$afterCacheFolder;
    
            $output->writeln("Full cache image file path: {$catalogMediaImageCacheFolder} ");
            
//optionally, if you want you can remove it !
            try {
                if ($this->file->isExists($catalogMediaImageCacheFolder)) {
                    $this->file->deleteFile($catalogMediaImageCacheFolder);
                }
            }catch (Exception $error){
                $output->writeln($error->getMessage());
            }
            $output->writeln("Finished!");
        }
    
        /**
         * @return array
         */
        public function getImageMiscParams() : array
        {
            return [
                'image_type' => 'small_image',
                'image_height' => 500,
                'image_width' => 500,
                'background' => [
                    0 => 255,
                    1 => 255,
                    2 => 255,
                ],
                'angle' => null,
                'quality' => 80,
                'keep_aspect_ratio' => true,
                'keep_frame' => false,
                'keep_transparency' => true,
                'constrain_only' => true,
            ];
        }
    }

Now if you run vendor:regenarate_image {product sku}, you will get the cache image patch and it will remove it. Good luck !

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.