Magento 2 Rest Api pobierz adres URL obrazu miniatury

12

W jaki sposób uzyskujemy adres URL do miniatury produktu za pośrednictwem interfejsu API spoczynku.

/V1/products/{sku}/media dostałby nam względny adres URL taki jak "/m/b/mb01-blue-0.jpg"

i URL obrazu będzie baseurl/catalog/product/m/b/mb01-blue-0.jpg

To działa dobrze. Ale w jaki sposób otrzymujemy miniaturę, która zwykle znajduje się w folderze pamięci podręcznej.

Mohammed Shameem
źródło
Nie ma takiej funkcjonalności po wyjęciu z pudełka. Musisz napisać niestandardowy interfejs API.
Sinisa Nedeljkovic

Odpowiedzi:

10

Jeśli potrzebujesz pełnej ścieżki obrazu miniatury z systemem pamięci podręcznej Magento 2 za pośrednictwem interfejsu API, możesz utworzyć niestandardowy interfejs API na podstawie natywnej klasy ProductRepository.

Utwórz nowy moduł. (wyjaśnione w innych postach)

Utwórz plik 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>

Utwórz plik 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>

Utwórz interfejs 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);
}

Utwórz model 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;
    }

}

Dostęp

Iść do /rest/V1/custom/products/{sku}

Powinieneś pobrać miniaturę z buforowanym adresem URL frontendu obrazu:

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

Komentarze:

Trzeci parametr funkcji startEnvironmentEmulation służy do wymuszenia użycia obszaru interfejsu użytkownika, jeśli użytkownik jest już w tym samym magazynie. (przydatne w obszarze API)

Nie testuję tego niestandardowego interfejsu API, możesz dostosować kod, ale logika jest poprawna, ale przetestowałem już część, aby pobrać adres URL obrazu w innym niestandardowym interfejsie API.

To obejście pozwala uniknąć tego rodzaju błędów:

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
źródło
Myślę, że ta praca może lepiej z \Magento\Catalog\Api\ProductRepositoryInterfaceFactoryzamiast \Magento\Catalog\Model\ProductFactory, ponieważ można wywołać get()na productRepositryobiekcie z SKU bezpośrednio. Przynajmniej tego teraz używam.
thaddeusmt
Nie zachęcamy do udostępnienia własnego interfejsu ProductRepositoryInterface, ponieważ taki istnieje w module katalogu. I przypuszczamy, że w razie potrzeby dostosujesz istniejący. Ponieważ idealnie wszyscy klienci, którzy są zależni od interfejsu ProductRepositoryInterface katalogu, nie powinni mieć wpływu na twoją zmianę. Istnieją dwa możliwe rozwiązania prawidłowego problemu: 1. Dodaj URL jako część ProductInterface jako atrybut rozszerzenia 2. Introuce dedykowana usługa rozpoznawania adresów URL. Pierwsze rozwiązanie nie pasuje do bieżącej architektury umowy o świadczenie usług, ponieważ ten atrybut powinien być tylko do odczytu.
Igor Minyaylo
Rzeczywiście, ta odpowiedź ma udowodnić możliwe obejście tego problemu. Najlepszym rozwiązaniem jest dodanie dedykowanej usługi rozpoznawania adresów URL i bazowanie na interfejsie API katalogu natywnego.
Franck Garnier
cześć @franck Garnier Dostaję błąd, jak pokazano na tym zrzucie ekranu prntscr.com/g5q4ak jak rozwiązać, proszę zasugerować, dziękuję?
Nagaraju K,
Twój błąd jest jawny, funkcja nie istnieje. Daję ci tylko przykładowy kod, ale musisz go dostosować do swoich potrzeb. Na przykład zaimplementuj funkcję getCacheKey, taką jak tutaj:vendor/magento/module-catalog/Model/ProductRepository.php:258
Franck Garnier
2

Powody, dla których Magento nie zapewnia tej funkcjonalności po wyjęciu z pudełka, są następujące:

  • Aby zwrócić URL miniatury obrazu jako część Produktu z atrybutem lub atrybutem rozszerzenia, będzie to oznaczać wprowadzenie obsługi atrybutów Tylko do odczytu (niemodyfikowalnych) w Obiektach danych. Ponieważ URL jest reprezentacją niektórych danych. Dane pochodzą z różnych źródeł, ponieważ nazwa domeny należy do konfiguracji systemu, ale ścieżka należy do modułu Katalog.
  • Na razie Magento nie obsługuje atrybutów ani usług tylko do odczytu dla API zapytań.

Jako rozwiązanie długoterminowe - interfejsy API zapytań powinny odpowiedzieć na to pytanie, ponieważ zapewnią możliwość pól tylko do odczytu i pól obliczeniowych. Jako rozwiązanie możemy zapewnić najbliższy czas społeczności - moglibyśmy wdrożyć / wprowadzić dedykowaną usługę rozpoznawania adresów URL, która zwróci adres URL dla określonych typów jednostek (takich jak Produkt, Kategoria, Obraz itp.)

Z tego samego powodu nie podajemy adresu URL produktu w ramach interfejsu ProductInterface

Oto moja odpowiedź na ten problem (adres URL produktu): https://community.magento.com/t5/Programming-Questions/Retrieving-the-product-URL-for-the-current-store-from-a/mp / 55387 / highlight / true # M1400

Igor Minyaylo
źródło
1
Kiedy taka usługa rozpoznawania adresów URL będzie dostępna od razu po wyjęciu z pudełka?
Franck Garnier
Odpowiedź pochodzi z 2017 roku. Czy od tego czasu została dodana w wersji Magenta 2.1.x 2.2.x lub 2.3.x?
Marcus Wolschon,
1

Powinno to być możliwe przy użyciu następującego adresu URL: /rest/V1/products/{sku}

Spowoduje to zwrócenie produktu i powinien istnieć węzeł dla niestandardowych atrybutów, który zawiera link do miniatury

<custom_attributes>
    <item>
        <attribute_code>thumbnail</attribute_code>
        <value>/m/b/mb01-blue-0.jpg</value>
    </item>
</custom_attributes>
DanCarlyon
źródło
cache / 1 / thumbnail / 88x110 / beff4985b56e3afdbeabfc89641a4582 / m / b / mb02-blue-0.jpg to lokalizacja miniatury. czy istnieje sposób na uzyskanie tego?
Mohammed Shameem,
/ V1 / products / {sku} / media and / rest / V1 / products / {sku} daje ten sam wynik, pierwszy daje same media, a później wszystkie inne informacje.
Mohammed Shameem,
@MohammedShameem znalazłeś jakieś działające rozwiązanie?
torayeff,
@torayeff jeszcze nie. Chyba będę musiał napisać jeden. Czy masz jakieś sugestie?
Mohammed Shameem,