I want to change Product Images to external Image URL in Magento 2 Frontend.

  • Product Listing Page.
  • Product Details Page Gallery.
  • Related Products.
  • Upsell Products listing.
  • Cross Sell Listing.
  • All Product Widget.
  • Cart Page and Minicart as well as in checkout Page.

On admin side I want to change Product Image in grid column.

Please help me To do this.

Thank you.

有帮助吗?

解决方案

To change All the Images to External Images Please follow below steps and create one module for that.

To change all Images in front-end you need to create four plugin for that to modify and change images with your custom external images.

First Create di.xml file

<VendorName>/<ModuleName>/etc/frontend/di.xml

<?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\Catalog\Block\Product\View\Gallery">
    <plugin name="add_images_to_gallery" type="<VendorName>\<ModuleName>\Plugin\AddImagesToGalleryBlock" />
</type>

<type name="Magento\Catalog\Block\Product\AbstractProduct">
    <plugin name="after_get_image_plugin" type="<VendorName>\<ModuleName>\Plugin\AfterGetImage"/>
</type>

<type name="Magento\Catalog\Block\Product\Image">
    <plugin name="after_get_image_url_plugin" type="<VendorName>\<ModuleName>\Plugin\AfterGetImageUrl"/>
</type>

<type name="Magento\Checkout\CustomerData\AbstractItem">
    <plugin name="minicart_after_get_itemdata_plugin" type="<VendorName>\<ModuleName>\Plugin\Minicart\AfterGetItemData"/>
</type>

</config>

Now You need to create a plugin files.

<VendorName>/<ModuleName>/Plugin/AddImagesToGalleryBlock.php

<?php

namespace <VendorName>\<ModuleName>\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 {
    $hasExternalImage = false;
    // logic to get your external images url
            if (!$hasExternalImage) {
                return $images;
            }
            $product = $subject->getProduct();
            $images = $this->dataCollectionFactory->create();
            $productName = $product->getName();
            $externalImages = ["https://static.integromat.com/img/packages/magento_256.png"]; // Array of images
            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;
        }

    }
}

<VendorName>/<ModuleName>/Plugin/AfterGetImage.php

<?php

namespace <vendorName>\<ModuleName>\Plugin;

use Magento\Catalog\Block\Product\AbstractProduct;

class AfterGetImage
{
    /**
     * AfterGetImage constructor.
     */
    public function __construct()
    {
    }

    /**
     * @param AbstractProduct $subject
     * @param $result
     * @param $product
     * @param $imageId
     * @param $attributes
     * @return mixed
     */
    public function afterGetImage(AbstractProduct $subject, $result, $product, $imageId, $attributes) {
        try {
            if ($product) {
                        $image = array();
                        $image['image_url'] = "https://static.integromat.com/img/packages/magento_256.png";
                        $image['width'] = "240";
                        $image['height'] = "300";
                        $image['label'] = $product->getName();
                        $image['ratio'] = "1.25";
                        $image['custom_attributes'] = "";
                        $image['resized_image_width'] = "399";
                        $image['resized_image_height'] = "399";
                        $image['product_id'] = $product->getId();
                if ($image) {
                    $result->setData($image);
                }
            }
        } catch (\Exception $e) {
        }
        return $result;
    }
}

<VendorName>\<ModuleName>\Plugin\AfterGetImageUrl.php

<?php

namespace <venfdorName>\<moduleName>\Plugin;

use Magento\Catalog\Block\Product\Image;

class AfterGetImageUrl
{
    /**
     * AfterGetImage constructor.
     */
    public function __construct(
    )
    {
    }

    /**
     * @param Image $image
     * @param $method
     * @return array|null
     */
    public function after__call(Image $image, $result, $method)
    {
        try {
            if ($method == 'getImageUrl' && $image->getProductId() > 0) {
                $result = "https://static.integromat.com/img/packages/magento_256.png";
            }
        } catch (\Exception $e) {
        }
        return $result;
    }

}

<VendorName>\<ModuleName>\Plugin\Minicart\AfterGetItemData.php

<?php

namespace <vendorName>\<moduleName>\Plugin\Minicart;

use Magento\Checkout\CustomerData\AbstractItem;

class AfterGetItemData
{
    /**
     * AfterGetImageData constructor.
     */
    public function __construct(
    )
    {
    }

    /**
     * @param AbstractItem $item
     * @param $result
     * @return mixed
     */
    public function afterGetItemData(AbstractItem $item, $result)
    {
        try {
            if ($result['product_id'] > 0) {
                $image = "https://static.integromat.com/img/packages/magento_256.png";
                $result['product_image']['src'] = $image;
            }
        } catch (\Exception $e) {
        }

        return $result;
    }

}

Thats all changes for Change images in storefront for product on all the places.

I hope it will help you.

其他提示

To add Images to Admin Grid Please follow below steps.

you need to override ui_component of listing for all product, relatedproduct, cross sale and upsale.

<vendorName>/<moduleName>/view/adminhtml/ui_component/product_listing.xml

<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <columns name="product_columns">
        <column name="thumbnail" class="<vendorName>\<moduleName>\Ui\Component\Listing\Column\Thumbnail" component="Magento_Ui/js/grid/columns/thumbnail" sortOrder="20">
            <settings>
                <altField>name</altField>
                <hasPreview>1</hasPreview>
                <addField>true</addField>
                <label translate="true">Thumbnail</label>
                <sortable>false</sortable>
            </settings>
        </column>
    </columns>
</listing>

<vendorName>/<moduleName>/view/adminhtml/ui_component/related_product_listing.xml

<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <columns name="product_columns">
        <column name="thumbnail" class="<vendorName>\<moduleName>\Ui\Component\Listing\Column\Thumbnail" component="Magento_Ui/js/grid/columns/thumbnail" sortOrder="20">
            <settings>
                <altField>name</altField>
                <hasPreview>1</hasPreview>
                <addField>true</addField>
                <label translate="true">Thumbnail</label>
                <sortable>false</sortable>
            </settings>
        </column>
    </columns>
</listing>

<vendorName>/<moduleName>/view/adminhtml/ui_component/upsell_product_listing.xml

<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <columns name="product_columns">
        <column name="thumbnail" class="<vendorName>\<moduleName>\Ui\Component\Listing\Column\Thumbnail" component="Magento_Ui/js/grid/columns/thumbnail" sortOrder="20">
            <settings>
                <altField>name</altField>
                <hasPreview>1</hasPreview>
                <addField>true</addField>
                <label translate="true">Thumbnail</label>
                <sortable>false</sortable>
            </settings>
        </column>
    </columns>
</listing>

<vendorName>/<moduleName>/view/adminhtml/ui_component/crosssell_product_listing.xml

<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <columns name="product_columns">
        <column name="thumbnail" class="<vendorName>\<moduleName>\Ui\Component\Listing\Column\Thumbnail" component="Magento_Ui/js/grid/columns/thumbnail" sortOrder="20">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="align" xsi:type="string">left</item>
                </item>
            </argument>
            <settings>
                <altField>name</altField>
                <hasPreview>1</hasPreview>
                <addField>true</addField>
                <label translate="true">Thumbnail</label>
                <sortable>false</sortable>
            </settings>
        </column>
    </columns>
</listing>

Now you need to create a UI component class file to render image content.

<vendorName>/&ltmoduleName>/Ui/Component/Listing/Column/Thumbnail.php

<?php
namespace <vendorName>\<moduleName>\Ui\Component\Listing\Column;

use Magento\Catalog\Helper\Image;
use Magento\Framework\DataObject;
use Magento\Framework\View\Element\UiComponentFactory;
use Magento\Framework\View\Element\UiComponent\ContextInterface;
use Magento\Ui\Component\Listing\Columns\Column;

/**
 * Class Thumbnail
 *
 * @api
 * @since 100.0.2
 */
class Thumbnail extends Column
{
    const NAME = 'thumbnail';

    const ALT_FIELD = 'name';

    /**
     * @param ContextInterface $context
     * @param UiComponentFactory $uiComponentFactory
     * @param Image $imageHelper
     * @param \Magento\Framework\UrlInterface $urlBuilder
     * @param array $components
     * @param array $data
     */
    public function __construct(
        ContextInterface $context,
        UiComponentFactory $uiComponentFactory,
        Image $imageHelper,
        \Magento\Framework\UrlInterface $urlBuilder,
        array $components = [],
        array $data = []
    ) {
        parent::__construct($context, $uiComponentFactory, $components, $data);
        $this->imageHelper = $imageHelper;
        $this->urlBuilder = $urlBuilder;
    }

    /**
     * @param array $dataSource
     * @return array
     */
    public function prepareDataSource(array $dataSource)
    {
        try {
            if (isset($dataSource['data']['items'])) {
                $fieldName = $this->getData('name');
                foreach ($dataSource['data']['items'] as & $item) {
                    $product = new DataObject($item);
                    $imageUrl = "https://static.integromat.com/img/packages/magento_256.png";
                    if ($imageUrl != "") {
                        $item[$fieldName . '_src'] = $imageUrl;
                        $item[$fieldName . '_alt'] = $this->getAlt($item) ?: $product->getName();
                        $item[$fieldName . '_link'] = $this->urlBuilder->getUrl(
                            'catalog/product/edit',
                            ['id' => $product->getEntityId(), 'store' => $this->context->getRequestParam('store')]
                        );
                        $item[$fieldName . '_orig_src'] = $imageUrl;

                    } else {
                        $imageHelper = $this->imageHelper->init($product, 'product_listing_thumbnail');
                        $item[$fieldName . '_src'] = $imageHelper->getUrl();
                        $item[$fieldName . '_alt'] = $this->getAlt($item) ?: $imageHelper->getLabel();
                        $item[$fieldName . '_link'] = $this->urlBuilder->getUrl(
                            'catalog/product/edit',
                            ['id' => $product->getEntityId(), 'store' => $this->context->getRequestParam('store')]
                        );
                        $origImageHelper = $this->imageHelper->init($product, 'product_listing_thumbnail_preview');
                        $item[$fieldName . '_orig_src'] = $origImageHelper->getUrl();
                    }
                }
            }
        } catch (\Exception $e) {
        }

        return $dataSource;
    }

    /**
     * Get Alt
     *
     * @param array $row
     *
     * @return null|string
     */
    protected function getAlt($row)
    {
        $altField = $this->getData('config/altField') ?: self::ALT_FIELD;
        return $row[$altField] ?? null;
    }
}

This is all about to change product images in admin grid.

I hope it will work for you.

Thank you.

I try to get this extension working, no error at creation and activation of the module, the extension working fine because in storefront i have the white logo https://static.integromat.com/img/packages/magento_256.png, however my external images are not found: i use the following custom attributes (as text field with urls inside):

small_image_url medium_image_url large_image_url

did i miss something?

EDIT:

i used the following method to get my url from custom attribute:

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$product = $objectManager->get('Magento\Catalog\Model\Product')->load($image->getProductId());
$result = $product->getYourCustomAtrribute();

attribute code can be: your_custom_attribute / Your_Custom_Attribute or yourcustomattribute / YourCustomAttribute.... Method will still be getYourCustomAtrribute()

hope this can help (you must integrate this in all other pages, now i steel need to construct the array for the main products pages)

full page: AfterGetImageUrl.php

/**
 * @param Image $image
 * @param $method
 * @return array|null
 */
public function after__call(Image $image, $result, $method)
{
    try {
        if ($method == 'getImageUrl' && $image->getProductId() > 0) {
            $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
            $product = $objectManager->get('Magento\Catalog\Model\Product')->load($image->getProductId());
            $result = $product->getYourCustomAtrribute();
        }
    } catch (\Exception $e) {
    }
    return $result;
}
许可以下: CC-BY-SA归因
scroll top