Magento 2 Rest Api获取缩略图图像URL


12

我们如何通过rest API获取产品缩略图的网址。

/V1/products/{sku}/media 会获得相对网址,例如 "/m/b/mb01-blue-0.jpg"

并且图片网址为 baseurl/catalog/product/m/b/mb01-blue-0.jpg

这很好。但是,我们如何获取通常驻留在缓存文件夹中的缩略图。


开箱即用没有这种功能。您必须编写自定义API。
Sinisa Nedeljkovic

Answers:


10

如果您需要通过API通过Magento 2缓存系统使用缩略图的完整路径,则可以基于本机ProductRepository类创建自定义API。

创建一个新模块。(在其他帖子中说明)

创建一个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>

创建一个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>

创建您的界面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);
}

创建模型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;
    }

}

访问

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

您应该检索缓存了图像前端URL的缩略图:

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

评论 :

如果您已经在同一storeId上,则函数startEnvironmentEmulation的第三个参数用于强制使用前端区域。(对API区域有用)

我没有测试此自定义API,您可以修改代码,但逻辑是正确的,但是我已经测试了该部分以在其他自定义API中检索图像URL。

此解决方法可以避免出现此类错误:

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'

我想这可能工作更好地与\Magento\Catalog\Api\ProductRepositoryInterfaceFactory替代的\Magento\Catalog\Model\ProductFactory,因为你可以叫get()productRepositry直接与SKU对象。至少,这就是我现在正在使用的。
thaddeusmt

我们不鼓励提供自己的ProductRepositoryInterface,因为Catalog模块提供了一个。我们假设您将根据需要自定义现有的。因为理想情况下,所有依赖Catalog的ProductRepositoryInterface的客户端都不会受到您的更改的影响。目前有两种可能的解决方案:1.将URL作为ProductInterface的一部分添加为扩展属性2.介绍专用的URL解析器服务。第一个解决方案不适合当前的Service Contract体系结构,因为此属性应为只读。
伊戈尔·米尼亚洛

确实,此答案是为了证明此问题的可能解决方法。最好的解决方案是添加专用的URL解析器服务,并基于本机目录API。
Franck Garnier

嗨@franck Garnier,我在屏幕截图中显示了错误prntscr.com/g5q4ak 如何解决,请建议我谢谢?
Nagaraju K

您的错误是明确的,该函数不存在。我只是给您一个代码示例,但是您需要根据需要对其进行调整。例如,实现如下所示的getCacheKey函数:vendor/magento/module-catalog/Model/ProductRepository.php:258
Franck Garnier

2

接下来,Magento不提供此功能的原因如下:

  • 将图像缩略图URL作为具有属性或扩展属性的产品的一部分返回,这意味着在数据对象中引入对只读(不可修改)属性的支持。因为URL是某些数据的表示。数据来自不同来源,因为域名属于系统配置,但路径属于目录模块。
  • 目前,Magento不支持Query API的只读属性或服务。

作为一种长期解决方案,查询API应该解决此问题,因为它们将提供只读和计算字段的功能。作为解决方案,我们可以提供社区最近的时间–我们可以实施/引入专用的URL解析器服务,该服务将返回特定实体类型(例如产品,类别,图像等)的URL。

出于相同的原因,我们不提供Product URL作为ProductInterface的一部分

这是我专门针对此问题的回复(产品URL):https : //community.magento.com/t5/Programming-Questions/Retrieving-the-product-URL-for-the-current-store-from-a/mp / 55387 / highlight / true#M1400


1
此类URL解析程序服务何时可用?
Franck Garnier

答案是从2017年开始的。此后是否已将其添加到洋红色2.1.x 2.2.x或2.3.x中?
Marcus Wolschon

1

可以使用以下网址: /rest/V1/products/{sku}

这将返回产品,并且应该有一个custom_attributes节点,其中包含缩略图链接

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

缓存/ 1 /缩略图/88x110/beff4985b56e3afdbeabfc89641a4582/m/b/mb02-blue-0.jpg这是缩略图位置。有没有办法得到这个?
Mohammed Shameem

/ V1 / products / {sku} / media和/ rest / V1 / products / {sku}得出相同的结果,前者仅提供媒体,而后者也提供所有其他信息。
Mohammed Shameem

@MohammedShameem您找到任何可行的解决方案了吗?
torayeff '16

@torayeff还没有。我猜将不得不写一个。你有建议吗?
Mohammed Shameem
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.