como salvar o atributo personalizado da imagem no magento 2

13

visualização no back-end

visualização no back-end 2

Preciso exibir algumas imagens do produto no front-end com base na condição: o uso do espelho virtual deve ser verificado.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Dcw\Vm\Observer;

use Magento\Framework\Event\ObserverInterface;

class ChangeTemplateObserver extends \Magento\ProductVideo\Observer\ChangeTemplateObserver
{
    /**
     * @param mixed $observer
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     * @return void
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $observer->getBlock()->setTemplate('Dcw_Vm::helper/gallery.phtml');
    }
}

Modelo:

<div class="admin__field field-image-vm">
    <div class="admin__field-control">
        <div class="admin__field admin__field-option">
            <input type="checkbox"
                   id="use-for-vm"
                   data-role="vm-save"
                   data-form-part="<?php /* @escapeNotVerified */ echo $formName ?>"
                   value="1"
                   class="admin__control-checkbox"
                   name="<?php /* @escapeNotVerified */ echo $elementName ?>[<%- data.file_id %>][vm]"
            <% if (data.useforvm == 1) { %>checked="checked"<% } %> />

            <label for="use-for-vm" class="admin__field-label">
                <?php /* @escapeNotVerified */ echo __('Use for Virutal Mirror')?>
            </label>
        </div>
    </div>
</div>

Script de instalação:

<?php

namespace Dcw\Vm\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Catalog\Model\ResourceModel\Product\Gallery;

class InstallSchema implements InstallSchemaInterface {

    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) {
        $setup->startSetup();

        $setup->getConnection()->addColumn(
                $setup->getTable(Gallery::GALLERY_TABLE), 'vm', [
            'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            'unsigned' => true,
            'nullable' => false,
            'default' => 0,
            'comment' => 'use for Vm'                ]
        );

        $setup->endSetup();
    }

}

Como salvar o estado das imagens verificadas no back-end? E como filtrar essas imagens no frontend? Você pode me ajudar nisso?

ATUALIZAR:

o seguinte observador (no evento catalog_product_save_after) para imagens existentes está funcionando, mas para novas imagens não estão funcionando.

<?php

namespace Dcw\Vm\Observer;

use Magento\Framework\Event\ObserverInterface;

class Productsaveafter implements ObserverInterface {

    protected $request;
    protected $resource;

    /**
     * 
     * @param \Magento\Framework\App\RequestInterface $request
     * @param \Magento\Framework\App\ResourceConnection $resource\
     */
    public function __construct(
    \Magento\Framework\App\RequestInterface $request, \Magento\Framework\App\ResourceConnection $resource
    ) {
        $this->request = $request;
        $this->resource = $resource;
    }

    public function execute(\Magento\Framework\Event\Observer $observer) {

        $vm = array();
        $data = $this->request->getPostValue();

        if (isset($data['product']['media_gallery']['images'])) {
            $images = $data['product']['media_gallery']['images'];

            foreach ($images as $image) {
                if (isset($image['vm']) && $image['vm'] == 1) {
                    $vm[$image['value_id']] = 1;
                } else {
                    $vm[$image['value_id']] = 0;
                }
            }
   // print_r($images);exit;
            $connection = $this->resource->getConnection();
            $tableName = 'catalog_product_entity_media_gallery'; //gives table name with prefix
            $product = $observer->getProduct();
            $mediaGallery = $product->getMediaGallery();

            if (isset($mediaGallery['images'])) {
                foreach ($mediaGallery['images'] as $image) {
                    if (isset($vm[$image['value_id']])) {
                        //Update Data into table
                        $sql = "Update " . $tableName . " Set vm = " . $vm[$image['value_id']] . " where value_id = " . $image['value_id'];
                        $connection->query($sql);
                    }
                }
            }
        }
    }

}
Siva Kumar Koduru
fonte
Qual evento você observa? Vou tentar reproduzi-lo e verificar por que não está funcionando.
Siarhey Uchukhlebau
catalog_product_save_after, se a imagem for um novo valor, o ID será nulo; portanto, a primeira vez não funcionará.
Siva Kumar Koduru
E qual evento você está usando para o ChangeTemplateObserver?
Siarhey Uchukhlebau
<preference for = tipo "Magento \ ProductVideo \ Observer \ ChangeTemplateObserver" = "DCW \ Vm \ Observer \ ChangeTemplateObserver" />
Siva Kumar Koduru
Minha resposta ajudou?
Siarhey Uchukhlebau

Respostas:

9

No seu observador, há muito código desnecessário. Você pode alterá-lo como:

<?php

namespace Dcw\Vm\Observer;

use Magento\Framework\Event\ObserverInterface;

class ProductSaveAfter implements ObserverInterface {

    protected $request;
    protected $resource;

    /**
     *
     * @param \Magento\Framework\App\RequestInterface $request
     * @param \Magento\Framework\App\ResourceConnection $resource\
     */
    public function __construct(
        \Magento\Framework\App\RequestInterface $request, \Magento\Framework\App\ResourceConnection $resource
    ) {
        $this->request = $request;
        $this->resource = $resource;
    }

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $data = $this->request->getPostValue();

        if (isset($data['product']['media_gallery']['images'])) {
            // print_r($images);exit;
            $connection = $this->resource->getConnection();
            $tableName = 'catalog_product_entity_media_gallery'; //gives table name with prefix
            $product = $observer->getProduct();
            $mediaGallery = $product->getMediaGallery();

            if (isset($mediaGallery['images'])) {
                foreach ($mediaGallery['images'] as $image) {
                        //Update Data into table
                    $vmValue = !empty($image['vm']) ? (int)$image['vm'] : 0;
                        $sql = "UPDATE " . $tableName . " SET vm = " . $vmValue . " WHERE value_id = " . $image['value_id'];
                        $connection->query($sql);
                }
            }
        }
    }

}

Como você não precisa armazenar dados de uma solicitação, como não existe value_idnas imagens recém-criadas, seus dados não permanecem ao adicionar a nova imagem.

Para obter dados em outros lugares, escrevi um plugin. Ao adicionar a coluna vmà galeria de mídia, selecione:

app / código / Dcw / Vm / 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">
    <type name="Magento\Catalog\Model\ResourceModel\Product\Gallery">
        <plugin name="afterCreateBatchBaseSelect" type="Dcw\Vm\Plugin\Product\Gallery" sortOrder="10" disabled="false"/>
    </type>
</config>

Código:

<?php

namespace Dcw\Vm\Plugin\Product;

class Gallery
{
    public function afterCreateBatchBaseSelect(
        \Magento\Catalog\Model\ResourceModel\Product\Gallery $subject,
        \Magento\Framework\DB\Select $select
    ) {
        $select->columns('vm');

        return $select;
    }
}

Portanto, agora seu atributo personalizado vmsempre deve existir nos dados de mídia do produto.

Para ocultar as imagens vm no frontend, você pode escrever o plugin:

app / código / Dcw / Vm / etc / frontend / 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">
    <type name="Magento\Catalog\Model\Product">
        <plugin name="afterGetMediaGalleryImages" type="Dcw\Vm\Plugin\Product" sortOrder="10" disabled="false"/>
    </type>
</config>

Código:

<?php

namespace Dcw\Vm\Plugin;

class Product
{
    /**
     * @param \Magento\Catalog\Model\Product $subject
     * @param \Magento\Framework\Data\Collection $result
     * @return mixed
     */
    public function afterGetMediaGalleryImages(\Magento\Catalog\Model\Product $subject, $result)
    {
        foreach ($result as $key => $image) {
            if ($image['vm']) {
                $result->removeItemByKey($key);
            }
        }

        return $result;
    }
}

Para obter as imagens vm do produto, use o código escrito por @Marius (sem um plug-in que exclua essas imagens):

$images = []; 
foreach ($product->getMediaGalleryImages() as $image) {
    if ($image->getVm()) {
        $images[] = $image;
    }
}
Siarhey Uchukhlebau
fonte
@SivaKumarKoduru Fico feliz em ajudá-lo
Siarhey Uchukhlebau
Olá, @Siarhey Uchukhlebau Eu tenho que implementar seu código no back-end.
Rasik Miyani
@SiarheyUchukhlebau Obrigado por isso, acho que estou quase lá: os atributos são salvos para mim, mas os valores não estão aparecendo no formulário de edição do produto? Querendo saber se você tem tempo, você pode ver o que eu fiz de errado? A pergunta menciona data.useforvm para extrair valores, no entanto, que não parece referenciado em nenhum lugar, existe uma etapa que estou perdendo? magento.stackexchange.com/questions/301685/…
harri
4

Recuperando no front-end:

Digamos que o produto para o qual você deseja exibir o espelho virtual seja $product.
Você pode obter as imagens marcadas com seu atributo personalizado como este:

$images = []; 
foreach ($product->getMediaGalleryImages() as $image) {
    if ($image->getVm()) {
        $images[] = $image;
    }
}

Depois, você pode percorrer a $imagesmatriz e exibi-la onde precisar.

Para salvar o valor dessa caixa de seleção no back-end, acho que você precisa escrever um afterplugin para o método \Magento\Catalog\Model\Product\Attribute\Backend\Media\ImageEntryConverter::convertFromem que anexa o valor que obtém da postagem no $entryArray.

Marius
fonte
em $ image não existe propriedade com vm, mas em db esse campo existia. portanto, sua matriz vazia retornando.
Siva Kumar Koduru
Está bem. Eu vou cavar mais.
Marius
qualquer ajuda sobre isso, realmente é algo difícil de gerenciar js no magento2.
Siva Kumar Koduru
Desculpe, não encontrei nada útil. Vou tentar ver se consigo alguma coisa depois do trabalho.
Marius