Magento 2 Rest Api erhalten Thumbnail Image url

12

Wie erhalten wir die URL zum Miniaturbild eines Produkts über die Rest-API?

/V1/products/{sku}/media würde uns die relative url besorgen wie "/m/b/mb01-blue-0.jpg"

und die Bild-URL wäre baseurl/catalog/product/m/b/mb01-blue-0.jpg

Das funktioniert gut. Aber wie bekommen wir die Miniaturansicht, die sich normalerweise im Cache-Ordner befindet.

Mohammed Shameem
quelle
Es gibt keine solche Funktionalität von Anfang an. Sie müssen eine benutzerdefinierte API schreiben.
Sinisa Nedeljkovic

Antworten:

10

Wenn Sie den vollständigen Pfad des Miniaturbilds mit dem Magento 2-Cache-System über die API benötigen, können Sie Ihre benutzerdefinierte API basierend auf der nativen ProductRepository-Klasse erstellen.

Erstellen Sie ein neues Modul. (erklärt in anderen Beiträgen)

Erstellen Sie eine etc / webapi.xml- Datei:

<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
    <route url="/V1/custom/products/{sku}" method="GET">
        <service class="Vendor\ModuleName\Api\ProductRepositoryInterface" method="get"/>
        <resources>
            <resource ref="Magento_Catalog::products"/>
        </resources>
    </route>
</routes>

Erstellen Sie eine etc / di.xml- Datei:

<?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Vendor\ModuleName\Api\ProductRepositoryInterface" type="Vendor\ModuleName\Model\ProductRepository" />
</config>

Erstellen Sie Ihre Schnittstelle Api \ ProductRepositoryInterface.php :

namespace Vendor\ModuleName\Api;

/**
 * @api
 */
interface ProductRepositoryInterface
{
    /**
     * Get info about product by product SKU
     *
     * @param string $sku
     * @param bool $editMode
     * @param int|null $storeId
     * @param bool $forceReload
     * @return \Magento\Catalog\Api\Data\ProductInterface
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function get($sku, $editMode = false, $storeId = null, $forceReload = false);
}

Erstellen Sie Ihr Modell Model \ ProductRepository.php :

namespace Vendor\ModuleName\Model;


class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterface
{
    /**
     * @var \Magento\Catalog\Model\ProductFactory
     */
    protected $productFactory;

    /**
     * @var Product[]
     */
    protected $instances = [];

    /**
     * @var \Magento\Catalog\Model\ResourceModel\Product
     */
    protected $resourceModel;

    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $storeManager;

    /**
     * @var \Magento\Catalog\Helper\ImageFactory
     */
    protected $helperFactory;

    /**
     * @var \Magento\Store\Model\App\Emulation
     */
    protected $appEmulation;

    /**
     * ProductRepository constructor.
     * @param \Magento\Catalog\Model\ProductFactory $productFactory
     * @param \Magento\Catalog\Model\ResourceModel\Product $resourceModel
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     */
    public function __construct(
        \Magento\Catalog\Model\ProductFactory $productFactory,
        \Magento\Catalog\Model\ResourceModel\Product $resourceModel,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Store\Model\App\Emulation $appEmulation,
        \Magento\Catalog\Helper\ImageFactory $helperFactory
    ) {
        $this->productFactory = $productFactory;
        $this->storeManager = $storeManager;
        $this->resourceModel = $resourceModel;
        $this->helperFactory = $helperFactory;
        $this->appEmulation = $appEmulation;
    }


    /**
     * {@inheritdoc}
     */
    public function get($sku, $editMode = false, $storeId = null, $forceReload = false)
    {
        $cacheKey = $this->getCacheKey([$editMode, $storeId]);
        if (!isset($this->instances[$sku][$cacheKey]) || $forceReload) {
            $product = $this->productFactory->create();

            $productId = $this->resourceModel->getIdBySku($sku);
            if (!$productId) {
                throw new NoSuchEntityException(__('Requested product doesn\'t exist'));
            }
            if ($editMode) {
                $product->setData('_edit_mode', true);
            }
            if ($storeId !== null) {
                $product->setData('store_id', $storeId);
            } else {
                // Start Custom code here

                $storeId = $this->storeManager->getStore()->getId();
            }
            $product->load($productId);

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

            $imageUrl = $this->getImage($product, 'product_thumbnail_image')->getUrl();

            $customAttribute = $product->setCustomAttribute('thumbnail', $imageUrl);

            $this->appEmulation->stopEnvironmentEmulation();

            // End Custom code here

            $this->instances[$sku][$cacheKey] = $product;
            $this->instancesById[$product->getId()][$cacheKey] = $product;
        }
        return $this->instances[$sku][$cacheKey];
    }

    /**
     * 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(75, 75);

        return $image;
    }

}

Zugriff

Gehe zu /rest/V1/custom/products/{sku}

Sie sollten das Miniaturbild mit der zwischengespeicherten Bild-Frontend-URL abrufen:

<custom_attributes>
    <item>
        <attribute_code>thumbnail</attribute_code>
        <value>http://{domain}/media/catalog/product/cache/1/thumbnail/75x75/e9c3970ab036de70892d86c6d221abfe/s/r/{imageName}.jpg</value>
    </item>
</custom_attributes>

Bemerkungen :

Der dritte Parameter der Funktion startEnvironmentEmulation wird verwendet, um die Verwendung des Frontend-Bereichs zu erzwingen, wenn Sie sich bereits in derselben storeId befinden. (nützlich für den API-Bereich)

Ich teste diese benutzerdefinierte API nicht. Sie können den Code anpassen, aber die Logik ist korrekt. Ich habe das Teil bereits getestet, um die Bild-URL in einer anderen benutzerdefinierten API abzurufen.

Diese Problemumgehung vermeidet, dass Sie diese Art von Fehlern haben:

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'
Franck Garnier
quelle
Ich denke , das könnte funktionieren besser mit der \Magento\Catalog\Api\ProductRepositoryInterfaceFactorystatt \Magento\Catalog\Model\ProductFactory, da Sie anrufen können get()auf dem productRepositryObjekt mit der Artikelnummer direkt. Zumindest benutze ich das jetzt.
Thaddeusmt
Es wird nicht empfohlen, ein eigenes ProductRepositoryInterface bereitzustellen, da dieses vom Catalog-Modul bereitgestellt wird. Wir gehen davon aus, dass Sie bei Bedarf die vorhandene Version anpassen. Denn im Idealfall sollten alle Clients, die vom ProductRepositoryInterface des Katalogs abhängig sind, von Ihrer Änderung nicht betroffen sein. Es gibt zwei mögliche Lösungen für ein aktuelles Problem: 1. Fügen Sie eine URL als Teil von ProductInterface als Erweiterungsattribut hinzu. 2. Introuce Dedicated URL Resolver Service. Die erste Lösung passt nicht zur aktuellen Architektur des Servicevertrags, da dieses Attribut schreibgeschützt sein sollte.
Igor Minyaylo
Mit dieser Antwort soll in der Tat eine mögliche Umgehung dieses Problems nachgewiesen werden. Die beste Lösung besteht darin, einen dedizierten URL-Auflösungsdienst hinzuzufügen und auf der nativen Katalog-API zu basieren.
Franck Garnier
hi @franck Garnier ich erhalte einen Fehler wie in diesem Screenshot gezeigt prntscr.com/g5q4ak wie zu lösen, bitte schlagen Sie mir vor, danke?
Nagaraju K
Ihr Fehler ist explizit, die Funktion existiert nicht. Ich gebe Ihnen nur ein Codebeispiel, aber Sie müssen es an Ihre Bedürfnisse anpassen. Implementieren Sie beispielsweise die Funktion getCacheKey wie folgt:vendor/magento/module-catalog/Model/ProductRepository.php:258
Franck Garnier
2

Die Gründe, warum Magento diese Funktionalität nicht sofort bereitstellt, sind folgende:

  • So geben Sie eine Miniaturbild-URL als Teil eines Produkts mit Attribut oder Erweiterungsattribut zurück, um die Unterstützung schreibgeschützter (nicht änderbarer) Attribute in Datenobjekten einzuführen. Weil URL eine Darstellung einiger Daten ist. Daten, die als Domänenname aus verschiedenen Quellen stammen, gehören zur Systemkonfiguration, der Pfad gehört jedoch zum Katalogmodul.
  • Derzeit unterstützt Magento keine schreibgeschützten Attribute oder Dienste für die Abfrage-API.

Als langfristige Lösung: Abfrage-APIs sollten diese Frage beantworten, da sie schreibgeschützte und berechnete Felder ermöglichen. Als eine Lösung, die wir für die nächste Community-Zeit bereitstellen könnten, könnten wir einen dedizierten URL-Auflösungsdienst implementieren / einführen, der die URL für bestimmte Entitätstypen (wie Produkt, Kategorie, Bild usw.) zurückgibt.

Aus dem gleichen Grund geben wir die Produkt-URL nicht als Teil von ProductInterface an

Hier ist meine Antwort zu diesem Thema (Produkt-URL): https://community.magento.com/t5/Programming-Questions/Retrieving-the-product-URL-for-the-current-store-from-a/mp / 55387 / highlight / true # M1400

Igor Minyaylo
quelle
1
Wann ist ein solcher URL-Auflösungsdienst sofort verfügbar?
Franck Garnier
Die Antwort stammt aus dem Jahr 2017. Wurde diese seitdem in Magenta 2.1.x 2.2.x oder 2.3.x hinzugefügt?
Marcus Wolschon
1

Es sollte mit der folgenden URL möglich sein: /rest/V1/products/{sku}

Dies gibt das Produkt zurück und es sollte einen Knoten für custom_attributes geben, der einen Thumbnail-Link enthält

<custom_attributes>
    <item>
        <attribute_code>thumbnail</attribute_code>
        <value>/m/b/mb01-blue-0.jpg</value>
    </item>
</custom_attributes>
DanCarlyon
quelle
cache / 1 / thumbnail / 88x110 / beff4985b56e3afdbeabfc89641a4582 / m / b / mb02-blue-0.jpg Dies ist die Position der Miniaturansicht. Gibt es einen Weg, dies zu bekommen?
Mohammed Shameem
/ V1 / products / {sku} / media und / rest / V1 / products / {sku} liefert das gleiche Ergebnis, erstere liefert nur die Medien und letztere liefert auch alle anderen Informationen.
Mohammed Shameem
@MohammedShameem hast du irgendeine funktionierende Lösung gefunden?
Torayeff
@torayeff noch nicht. Ich muss wohl einen schreiben. Hast du irgendwelche Vorschläge?
Mohammed Shameem