Magento 2 Rest Api obtenir l'URL de l'image miniature


12

Comment obtenir l'URL de l'image miniature d'un produit via l'API rest.

/V1/products/{sku}/media nous obtiendrait l'URL relative telle que "/m/b/mb01-blue-0.jpg"

et l'url de l'image serait baseurl/catalog/product/m/b/mb01-blue-0.jpg

Cela fonctionne bien. Mais comment obtenir la vignette qui réside généralement dans le dossier cache.


Il n'y a pas une telle fonctionnalité prête à l'emploi. Vous devrez écrire une API personnalisée.
Sinisa Nedeljkovic

Réponses:


10

Si vous avez besoin du chemin complet de l'image miniature avec le système de cache Magento 2 via l'API, vous pouvez créer votre API personnalisée basée sur la classe native ProductRepository.

Créez un nouveau module. (expliqué dans d'autres articles)

Créez un fichier etc / webapi.xml :

<?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>

Créez un fichier etc / 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">
    <preference for="Vendor\ModuleName\Api\ProductRepositoryInterface" type="Vendor\ModuleName\Model\ProductRepository" />
</config>

Créez votre interface 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);
}

Créez votre modèle 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;
    }

}

Accès

Aller à /rest/V1/custom/products/{sku}

Vous devez récupérer l'image miniature avec l'URL du frontend de l'image mise en cache:

<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>

Commentaires :

Le troisième paramètre de la fonction startEnvironmentEmulation est utilisé pour forcer l'utilisation de la zone frontend si vous êtes déjà sur le même storeId. (utile pour la zone API)

Je ne teste pas cette API personnalisée, vous pouvez adapter le code mais la logique est correcte mais j'ai déjà testé la partie pour récupérer l'URL de l'image dans d'autres API personnalisées.

Cette solution de contournement vous évite d'avoir ce type d'erreurs:

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'

Je pense que cela pourrait mieux fonctionner avec le \Magento\Catalog\Api\ProductRepositoryInterfaceFactoryau lieu de \Magento\Catalog\Model\ProductFactory, puisque vous pouvez appeler directement get()l' productRepositryobjet avec le SKU. Du moins, c'est ce que j'utilise maintenant.
thaddeusmt

Nous n'encourageons pas à fournir votre propre ProductRepositoryInterface, car il y en a un fourni par le module Catalogue. Et nous supposons que vous en personnaliserez un si nécessaire. Parce que, idéalement, tous les clients qui dépendent de ProductRepositoryInterface du catalogue ne devraient pas être affectés par votre modification. Il existe deux solutions possibles pour le problème actuel: 1. Ajouter une URL en tant que partie de ProductInterface en tant qu'attribut d'extension 2. Introuce un service de résolution d'URL dédié. La première solution ne correspond pas à l'architecture actuelle du contrat de service, car cet attribut doit être en lecture seule.
Igor Minyaylo

En effet, cette réponse consiste à mettre en évidence une solution possible à ce problème. La meilleure solution consiste à ajouter un service de résolution d'URL dédié et basé sur l'API de catalogue natif.
Franck Garnier

salut @franck Garnier je reçois une erreur comme indiqué dans cette capture d'écran prntscr.com/g5q4ak comment résoudre s'il vous plaît me suggérer merci?
Nagaraju K

Votre erreur est explicite, la fonction n'existe pas. Je vous donne juste un exemple de code, mais vous devez l'adapter à vos besoins. Par exemple, implémentez la fonction getCacheKey comme celle-ci:vendor/magento/module-catalog/Model/ProductRepository.php:258
Franck Garnier

2

Les raisons pour lesquelles Magento ne fournit pas cette fonctionnalité prête à l'emploi sont les suivantes:

  • Pour renvoyer l'URL de vignette d'image en tant que partie du produit avec un attribut ou un attribut d'extension qui signifiera introduire la prise en charge des attributs en lecture seule (non modifiables) dans les objets de données. Parce que l'URL est une représentation de certaines données. Les données proviennent de différentes sources, car le nom de domaine appartient à la configuration du système, mais le chemin appartient au module Catalogue.
  • Pour l'instant, Magento ne prend pas en charge les attributs ou le service en lecture seule pour l'API de requête.

En tant que solution à long terme - les API de requête devraient répondre à cette question, car elles fourniront une capacité pour les champs en lecture seule et calculés. En tant que solution, nous pourrions fournir le temps le plus proche de la communauté - nous pourrions implémenter / introduire un service de résolution d'URL dédié qui retournera l'URL pour des types d'entités spécifiques (comme le produit, la catégorie, l'image, etc.)

Pour la même raison, nous ne fournissons pas l'URL du produit dans le cadre de ProductInterface

Voici ma réponse consacrée à ce problème (URL du produit): https://community.magento.com/t5/Programming-Questions/Retrieving-the-product-URL-for-the-current-store-from-a/mp / 55387 / surlignage / vrai # M1400


1
Quand un tel service de résolution d'URL sera-t-il disponible immédiatement?
Franck Garnier

La réponse est de 2017. Cela a-t-il été ajouté depuis Magenta 2.1.x 2.2.x ou 2.3.x depuis?
Marcus Wolschon

1

Cela devrait être possible avec l'url suivante: /rest/V1/products/{sku}

Cela retournera le produit et il devrait y avoir un nœud pour custom_attributes qui contient un lien miniature

<custom_attributes>
    <item>
        <attribute_code>thumbnail</attribute_code>
        <value>/m/b/mb01-blue-0.jpg</value>
    </item>
</custom_attributes>

cache / 1 / thumbnail / 88x110 / beff4985b56e3afdbeabfc89641a4582 / m / b / mb02-blue-0.jpg il s'agit de l'emplacement de la miniature. existe-t-il un moyen d'obtenir cela?
Mohammed Shameem

/ V1 / products / {sku} / media et / rest / V1 / products / {sku} donne le même résultat que le premier donne le média seul et le dernier donne également toutes les autres informations.
Mohammed Shameem

@MohammedShameem avez-vous trouvé une solution de travail?
torayeff

@torayeff pas encore. Je suppose que je devrai en écrire un. Avez-vous des suggestions?
Mohammed Shameem
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.