Magento 2 Rest Api obter miniatura da imagem url

12

Como obtemos o URL para miniatura da imagem de um produto por meio da API de descanso.

/V1/products/{sku}/media nos daria o URL relativo, como "/m/b/mb01-blue-0.jpg"

e o URL da imagem seria baseurl/catalog/product/m/b/mb01-blue-0.jpg

Isso funciona bem. Mas como obtemos a miniatura que geralmente reside na pasta de cache.

Mohammed Shameem
fonte
Não existe essa funcionalidade pronta para uso. Você precisará escrever uma API personalizada.
Sinisa Nedeljkovic 28/02

Respostas:

10

Se você precisar do caminho completo da imagem em miniatura com o sistema de cache Magento 2 por meio da API, poderá criar sua API personalizada com base na classe ProductRepository nativa.

Crie um novo módulo. (explicado em outras postagens)

Crie um arquivo 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>

Crie um arquivo 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>

Crie sua 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);
}

Crie o seu modelo 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;
    }

}

Acesso

Vamos para /rest/V1/custom/products/{sku}

Você deve recuperar a imagem em miniatura com o URL de front-end da imagem em 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>

Comentários :

O terceiro parâmetro da função startEnvironmentEmulation é usado para forçar o uso da área de front-end se você já estiver no mesmo storeId. (útil para a área da API)

Não testei essa API personalizada, você pode adaptar o código, mas a lógica está correta, mas já testei a parte para recuperar o URL da imagem em outra API personalizada.

Esta solução alternativa evita que você tenha esse tipo de erro:

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
fonte
Eu acho que isso pode funcionar melhor com o \Magento\Catalog\Api\ProductRepositoryInterfaceFactoryinvés de \Magento\Catalog\Model\ProductFactory, já que você pode chamar get()o productRepositryobjeto diretamente com o SKU. Pelo menos, é o que estou usando agora.
Thaddeusmt
Não recomendamos o fornecimento de ProductRepositoryInterface, porque existe um fornecido pelo módulo Catalog. E supomos que você personalizará um existente, se necessário. Como idealmente, todos os clientes que dependem do ProductRepositoryInterface do catálogo não devem ser afetados com sua alteração. Existem duas soluções possíveis para o problema de cobrança: 1. Adicione o URL como parte do ProductInterface como atributo de extensão 2. Introduza um serviço de resolução de URL dedicado. A primeira solução não se encaixa na arquitetura atual do contrato de serviço, porque esse atributo deve ser somente leitura.
Igor Minyaylo
De fato, essa resposta é colocar em evidência uma possível solução alternativa para esse problema. A melhor solução é adicionar um serviço de resolução de URL dedicado e com base na API do catálogo nativo.
Franck Garnier
oi @franck Garnier Estou recebendo um erro, como mostrado nesta captura de tela prntscr.com/g5q4ak como resolver, por favor me sugerir obrigado?
precisa saber é o seguinte
Seu erro é explícito, a função não existe. Eu apenas cito um exemplo de código, mas você precisa adaptá-lo às suas necessidades. Por exemplo, implemente a função getCacheKey, como aqui:vendor/magento/module-catalog/Model/ProductRepository.php:258
Franck Garnier
2

Os motivos pelos quais o Magento não fornece essa funcionalidade imediatamente são os seguintes:

  • Para retornar o URL da miniatura da imagem como parte do Produto com atributo ou atributo de extensão que significa introduzir suporte aos atributos Somente Leitura (não modificáveis) nos Objetos de Dados. Porque URL é uma representação de alguns dados. Dados obtidos de diferentes origens, como o nome de domínio pertence à configuração do sistema, mas o caminho pertence ao módulo Catalog.
  • Por enquanto, o Magento não suporta atributos ou serviço somente leitura para a API de consulta.

Como uma solução a longo prazo - as APIs de consulta devem abordar esta questão, pois fornecerão a capacidade de campos somente leitura e computados. Como uma solução que poderíamos oferecer ao tempo mais próximo da comunidade - poderíamos implementar / introduzir um serviço de resolução de URL dedicado, que retornará URL para tipos de entidade específicos (como Produto, Categoria, Imagem etc.)

Pelo mesmo motivo, não fornecemos o URL do produto como parte do ProductInterface

Aqui está minha resposta dedicada a esse problema (URL do produto): https://community.magento.com/t5/Programming-Questions/Retrieving-the-product-URL-for-the-current-store-from-a/mp / 55387 / realce / verdadeiro # M1400

Igor Minyaylo
fonte
1
Quando um serviço desse tipo de resolvedor de URL estará disponível imediatamente?
Franck Garnier #
A resposta é: 2017. Isso foi adicionado no Magenta 2.1.x 2.2.x ou 2.3.x desde então?
Marcus Wolschon 13/09/18
1

Isso deve ser possível com o seguinte URL: /rest/V1/products/{sku}

Isso retornará o produto e deve haver um nó para custom_attributes que contém um link de miniatura

<custom_attributes>
    <item>
        <attribute_code>thumbnail</attribute_code>
        <value>/m/b/mb01-blue-0.jpg</value>
    </item>
</custom_attributes>
DanCarlyon
fonte
cache / 1 / thumbnail / 88x110 / beff4985b56e3afdbeabfc89641a4582 / m / b / mb02-blue-0.jpg este é o local da miniatura. existe uma maneira de conseguir isso?
Mohammed Shameem
/ V1 / products / {sku} / media e / rest / V1 / products / {sku} fornece o mesmo resultado que o primeiro fornece a mídia sozinho e o posterior também fornece todas as outras informações.
Mohammed Shameem
@MohammedShameem você encontrou alguma solução de trabalho?
torayeff
@torayeff ainda não. Eu acho que terá que escrever um. Você tem alguma sugestão?
Mohammed Shameem