Magento 2 Rest Api obtener imagen en miniatura url

12

¿Cómo obtenemos la URL para obtener una imagen en miniatura de un producto a través de la API de descanso?

/V1/products/{sku}/media nos daría la URL relativa como "/m/b/mb01-blue-0.jpg"

y la url de la imagen sería baseurl/catalog/product/m/b/mb01-blue-0.jpg

Esto funciona bien Pero, ¿cómo obtenemos la miniatura que generalmente reside en la carpeta de caché.

Mohammed Shameem
fuente
No existe tal funcionalidad fuera de la caja. Tendrás que escribir API personalizada.
Sinisa Nedeljkovic

Respuestas:

10

Si necesita la ruta completa de la imagen en miniatura con el sistema de caché Magento 2 a través de la API, puede crear su API personalizada basada en la clase de ProductRepository nativa.

Crea un nuevo módulo. (explicado en otras publicaciones)

Cree un archivo 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>

Cree un archivo 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>

Cree su interfaz 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);
}

Cree su 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;
    }

}

Acceso

Ir /rest/V1/custom/products/{sku}

Debería recuperar la imagen en miniatura con la URL de la interfaz de la imagen almacenada en caché:

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

Comentarios:

El tercer parámetro de la función startEnvironmentEmulation se usa para forzar el uso del área frontend si ya está en el mismo storeId. (útil para el área API)

No pruebo esta API personalizada, puede adaptar el código pero la lógica es correcta, pero ya probé la parte para recuperar la URL de la imagen en otra API personalizada.

Esta solución evita que tengas este tipo de errores:

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
fuente
Creo que esto podría funcionar mejor con el en \Magento\Catalog\Api\ProductRepositoryInterfaceFactorylugar de \Magento\Catalog\Model\ProductFactory, ya que puede invocar get()el productRepositryobjeto con el SKU directamente. Al menos, eso es lo que estoy usando ahora.
thaddeusmt
No recomendamos proporcionar su propia interfaz ProductRepositoryInterface, porque hay una proporcionada por el módulo Catálogo. Y suponemos que personalizará uno existente si es necesario. Porque, idealmente, todos los clientes que dependen de ProductRepositoryInterface del catálogo no deberían verse afectados con su cambio. Hay dos posibles soluciones para el problema correcto: 1. Agregar URL como parte de ProductInterface como atributo de extensión 2. Introuce el servicio dedicado de resolución de URL. La primera solución no se ajusta a la arquitectura actual del contrato de servicio, porque este atributo debe ser de solo lectura.
Igor Minyaylo
De hecho, esta respuesta es poner en evidencia una posible solución a este problema. La mejor solución es agregar un servicio de resolución de URL dedicado y basado en la API nativa del catálogo.
Franck Garnier
hola @franck Garnier recibo un error como se muestra en esta captura de pantalla prntscr.com/g5q4ak cómo resolverlo, ¿me sugieres gracias?
Nagaraju K
Su error es explícito, la función no existe. Solo te doy un ejemplo de código, pero debes adaptarlo a tus necesidades. Por ejemplo, implemente la función getCacheKey como aquí:vendor/magento/module-catalog/Model/ProductRepository.php:258
Franck Garnier
2

Las razones por las que Magento no proporciona esta funcionalidad de manera inmediata son las siguientes:

  • Para devolver la URL de la imagen en miniatura de la imagen como parte del Producto con un atributo o atributo de extensión que significará introducir soporte de atributos de Solo lectura (no modificable) en Objetos de datos. Porque la URL es una representación de algunos datos. Datos tomados de diferentes fuentes, ya que el nombre de dominio pertenece a la configuración del sistema, pero la ruta pertenece al módulo Catálogo.
  • Por ahora, Magento no admite atributos o servicio de solo lectura para la API de consulta.

Como solución a largo plazo: las API de consulta deben abordar esta pregunta, ya que proporcionarán la capacidad de campos de solo lectura y calculados. Como solución podríamos proporcionar el tiempo más cercano a la comunidad, podríamos implementar / introducir un servicio dedicado de resolución de URL que devolverá la URL para tipos de entidad específicos (como Producto, Categoría, Imagen, etc.)

Por el mismo motivo, no proporcionamos la URL del producto como parte de ProductInterface

Aquí está mi respuesta dedicada a este problema (URL del producto): https://community.magento.com/t5/Programming-Questions/Retrieving-the-product-URL-for-the-current-store-from-a/mp / 55387 / resaltado / verdadero # M1400

Igor Minyaylo
fuente
1
¿Cuándo estará disponible un servicio de resolución de URL de este tipo?
Franck Garnier
La respuesta es de 2017. ¿Se ha agregado esto en Magenta 2.1.x 2.2.xo 2.3.x desde entonces?
Marcus Wolschon el
1

Debería ser posible con la siguiente url: /rest/V1/products/{sku}

Esto devolverá el producto y debería haber un nodo para atributos_personalizados que contiene un enlace en miniatura

<custom_attributes>
    <item>
        <attribute_code>thumbnail</attribute_code>
        <value>/m/b/mb01-blue-0.jpg</value>
    </item>
</custom_attributes>
DanCarlyon
fuente
caché / 1 / miniatura / 88x110 / beff4985b56e3afdbeabfc89641a4582 / m / b / mb02-blue-0.jpg esta es la ubicación en miniatura. ¿hay alguna manera de conseguir esto?
Mohammed Shameem
/ V1 / products / {sku} / media y / rest / V1 / products / {sku} da el mismo resultado que el primero da solo los medios y el segundo da toda la otra información también.
Mohammed Shameem
@MohammedShameem ¿ha encontrado alguna solución de trabajo?
torayeff
@torayeff aún no. Supongo que tendrá que escribir uno. ¿Tienes alguna sugerencia?
Mohammed Shameem