0

We have a custom module to show images from sw3 on the product page, so the main image and any gallery images. The code works but going from a list page to the PDP is very slow and when I disable this module so that Magento uses images that have been uploaded things speed up dramatically so I think this custome module is slowing things down a lot. I'm wondering is it the code itself or the fact that it's calling s3.amazonaws.com that is the issue. Is there any way to speed it up?

(Since it works, I'm not going to include the di.xml, module.xml and registration.php files)

Plugin/AddImagesToGalleryBlock.php

<?php

namespace XX\CDNExtraImages\Plugin;

use Magento\Catalog\Block\Product\View\Gallery;
use Magento\Framework\Data\Collection;
use Magento\Framework\Data\CollectionFactory;
use Magento\Framework\DataObject;

class AddImagesToGalleryBlock
{
    /**
     * @var CollectionFactory
     */
    protected $dataCollectionFactory;

    /**
     * AddImagesToGalleryBlock constructor.
     *
     * @param CollectionFactory $dataCollectionFactory
     */
    public function __construct(
        CollectionFactory $dataCollectionFactory
    ) {
        $this->dataCollectionFactory = $dataCollectionFactory;
    }

    /**
     * afterGalleryImages Plugin to change images and use external images stored in custom attribute
     *
     * @param Gallery $subject
     * @param Collection|null $images
     * @return Collection|null
     */
    public function afterGetGalleryImages(Gallery $subject, $images) {
        try {
            $product = $subject->getProduct();
            $images = $this->dataCollectionFactory->create();
            $productName = $product->getName();
            $sku = $product->getSku();
            $externalImages  = array();
            $baseimage = "https://xxx.s3.amazonaws.com/".$sku.".jpg";

            $base_headers = @get_headers($baseimage);
            if(!$base_headers || $base_headers[0] == 'HTTP/1.1 404 Not Found') {
                $baseimage = "https://xxx.s3.amazonaws.com/placeholder.jpg";
            }

            $externalImages[0] = $baseimage;
            $max = 5;
            //$exists = true;
            for ($x = 1; $x <= $max; $x++) {
                $newimage = "https://xxx.s3.amazonaws.com/".$sku."_".$x.".jpg";
                $file_headers = @get_headers($newimage);
                if(!$file_headers || $file_headers[0] == 'HTTP/1.1 404 Not Found') {
                    //$exists = false;
                    break;
                }
                else {
                    //$exists = true;
                    array_push($externalImages, $newimage);
                }
            }
           
            foreach ($externalImages as $item) {
                $imageId    = uniqid();
                $small      = $item;
                $medium     = $item;
                $large      = $item;
                $image = [
                    'file' => $large,
                    'media_type' => 'image',
                    'value_id' => $imageId, // unique value
                    'row_id' => $imageId, // unique value
                    'label' => $productName,
                    'label_default' => $productName,
                    'position' => 100,
                    'position_default' => 100,
                    'disabled' => 0,
                    'url'  => $large,
                    'path' => '',
                    'small_image_url' => $small,
                    'medium_image_url' => $medium,
                    'large_image_url' => $large
                ];
                $images->addItem(new DataObject($image));
            }

            return $images;
        } catch (\Exception $e) {
            return $images;
        }

    }
}

Thanks for any help.

ETA - in response to byalexes' answer. I am waiting to get client's credentials. But in the meantime, should it be something like the following? Do I need to put the s3 address in the Magento admin as the Base url for media files? We do have images imported into magento for the lists etc so don't want to go to s3 for everything.

....
$sku = $product->getSku();
           
            $credentials = new \Aws\Credentials\Credentials($key, $secret);
            $s3Client = new \Aws\S3\S3Client([
                'version' => $version,
                'region' => $region,
                'credentials' => $credentials
            ]);

            $externalImages = $s3Client->getIterator('ListObjects', ['Bucket' => $bucket, 'Prefix' => $sku]); 
           
            foreach ($externalImages as $item) {$imageId    = uniqid();
            $small      = $item;
            $medium     = $item;
            $large      = $item;
            $image = [
                'file' => $large,
                'media_type' => 'image',
                .......
            ];
            $images->addItem(new DataObject($image));
        }

        return $images;

2 Answers 2

0

My guess is that with this code you are going to get the images to the remote amazon website all the time ; each time the gallery will be called (which is actually kinda dumb cause you don't need to do that treatment more than once for every image).

What you should do I think is running a script that will update the images once and then let magento works as usual.

Or at least add a condition that won't search again for the images you already have.

3
  • Once the page caches it runs nice and fast, it's just the first time. The client run a product import nightly with the base image but didn't want to be inputting all the gallery images, so we came up with this plan. I'm thinking now that we should just put the gallery images into the import also. Bit more work on their end but much faster for the customer Commented Feb 23, 2022 at 14:29
  • Sadly i don't see any more solution for that, magento (or any website^^) is always more slow when he has to load media for the first time. I never heard about importing a product and not updating the gallery at the same time. I even think it's automatic if you update products property like Thumbnail image etc etc
    – Claims
    Commented Feb 23, 2022 at 14:35
  • It is to do with their inhouse system - the people updating the database don't always know how many gallery images there are, so they asked if we could get them on the fly from the amazon s3 site. Commented Feb 23, 2022 at 16:13
0

Of course, everything will be rather slow, because. in your script, you need to separately check the response headers for each image. There are ways, firstly, faster in terms of performance, and secondly, more beautiful and simple. For example, why don't you want to use the standard library, which is even pre-installed in Magento 2. Here is a small example:

    $credentials = new \Aws\Credentials\Credentials($key, $secret);
    $s3Client = new \Aws\S3\S3Client([
        'version' => $version,
        'region' => $region,
        'credentials' => $credentials
    ]);

    $objects = $s3Client->getIterator('ListObjects', ['Bucket' => $bucket, 'Prefix' => $sku]); 

So we got a list of all pictures starting with $sku. Next, for example, we can go through the foreach loop through all the relevant files and get any necessary values.

foreach ($objects as $object) {
    $fileName = $object['Key'];
    $modifiedImage = $object['LastModified'];
}

And these are not all the elements contained in the object. For more details see var_dump($object)

1
  • Thank you very much. I have edited my original post with modified code and a question, if you don't mind. This s3 in Magento is all new to me I'm afraid. Commented Feb 25, 2022 at 12:40

Your Answer

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

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