Redefinir "Usar valor padrão" para exibição específica da loja em todos os produtos

16

De alguma forma, vários dos meus produtos tiveram a opção "Usar valor padrão" desmarcada.

Minha loja possui 2 idiomas, inglês e francês. O francês usa o valor da Loja padrão. Agora, quando eu atualizo os produtos, ele não aparece no front-end, a menos que eu entre manualmente no produto na exibição da loja francesa e selecione "Usar valor padrão",

Não parece haver um atributo para uma ação em massa; já deparei com alguns scripts e consultas MySQL. No entanto, não está claro se essas soluções redefinem todas as visualizações da loja para usar o valor padrão.

O resultado desejado é definir "Usar valor padrão" em uma visualização específica da loja (francês) em todos os produtos.

Como redefinir um grande número de produtos (ou todos os produtos) para "Usar valor padrão" em uma exibição específica da loja?

SR_Magento
fonte

Respostas:

7

Infelizmente, nenhuma das maneiras eficientes de atualizar um atributo do produto funciona nesse caso. $product->getResource()->saveAttribute()atualiza o atributo para todas as visualizações da loja, mesmo se você definir o ID da loja no $productobjeto. Mage::getSingleton('catalog/product_action')->updateAttributes()atualiza apenas o valor em uma loja específica, mas não pode definir o atributo para usar o valor padrão (consulte também a pergunta Estouro de pilha para obter uma referência). Portanto, temos que usar a maneira lenta e intensiva de memória $product->save().

Presumo que você saiba quais atributos você gostaria de atualizar. Para o exemplo a seguir, defino o visibilityatributo para usar o valor padrão. O script a seguir deve fazer o truque (certifique-se de alterá-lo de acordo com suas necessidades):

<?php

error_reporting(E_ALL);
ini_set('display_errors', '1');

require_once 'app/Mage.php';
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
set_time_limit(0);

function useDefaultValueCallback($args)
{
    // change to the ID of your french store view
    $specificStoreViewId = 7;
    $product = Mage::getModel('catalog/product');
    $product->setData($args['row']);
    $product->setStoreId($specificStoreViewId);
    // change according to your needs
    $product->setData('visibility', false);
    $product->save();
}

$products = Mage::getModel('catalog/product')->getCollection();
Mage::getSingleton('core/resource_iterator')->walk($products->getSelect(), array('useDefaultValueCallback'));
Simon
fonte
Existe uma maneira de marcar o "usar valor padrão" sem alterar os dados do atributo? Porque aqui, se eu usar $product->setData('visibility', false);ele vai assinalar a caixa, mas também definir a visibilidade como "true", o que eu não quero
Jurģis Toms Liepiņš
1
@ JurģisTomsLiepiņš Se você marcar a caixa, ela usará o valor padrão, que é o valor do escopo pai. Portanto, se você marcar a caixa e ela mudar para "true", o valor do escopo pai também será "true". Para mais perguntas, faça uma nova pergunta.
Simon #
Pedi uma nova pergunta , eu espero que você possa esclarecer / limpar algumas coisas para mim
Jurģis Toms Liepiņš
Eu uso o setData para false com sucesso (quando chamado de cli). Mas notei que quando chamo a mesma função de uma rota de controlador de front-end, ela não funciona! Alguém já enfrentou esse problema?
precisa saber é o seguinte
@DarkCowboy Esta é provavelmente uma questão de permissão. Eu não acho que você pode salvar um produto em um controlador de front-end. Para mais perguntas, abra uma nova.
Simon
24

Supondo que o ID da loja francesa seja 2, você deve executar as consultas mysql abaixo:

DELETE FROM `catalog_product_entity_text` where store_id = 2;
DELETE FROM `catalog_product_entity_datetime` where store_id = 2;
DELETE FROM `catalog_product_entity_decimal` where store_id = 2;
DELETE FROM `catalog_product_entity_int` where store_id = 2;
DELETE FROM `catalog_product_entity_varchar` where store_id = 2;

Isso basicamente exclui os valores de atributo para todos os atributos e produtos para os quais o ID da loja está definido como 2. Quando o Magento não consegue encontrar o valor do atributo para um produto no ID da loja específico, ele escolhe o valor padrão.

Paras Sood
fonte
1
Isso não é verdade. Se alguém definir o valor do atributo falsecomo eu fiz, a opção "usar valor padrão" será marcada. Embora sua solução possa funcionar, eu pessoalmente não gosto de usar consultas SQL diretas.
Simon
Ok, desculpe, eu interpretei mal sua resposta e pensei que você estava pedindo ao OP para colocar todos os valores padrão em vez de falso. Sua solução funciona :)
Paras Sood
5
Observe que "Isso não é verdade" refere-se a um comentário na resposta de Simon que agora foi removido. A solução funciona.
Fabian Schmengler
@fschmengler A Paras responderia ao trabalho para mostrar as imagens no front end? Tenho o mesmo problema na minha nova loja, todos os produtos e imagens estão lá, mas não estão selecionados para usar como padrão.
thismethod
@thismethod não, isso é algo diferente. Pode haver uma pergunta para já, caso contrário, por favor, peça um novo
Fabian Schmengler
7

Aderir um pouco tarde, mas eu realmente não gostei de nenhuma das respostas acima.

  1. A resposta de Simons ao caminhar sobre a coleção de produtos é incrivelmente lenta e ineficiente, no entanto, é pelo menos usando o Magento
  2. A resposta da ParasSood de fazer modificações diretas no banco de dados é um pouco assustadora e não é muito útil se você quiser isso como um pouco de funcionalidade automatizada.

Aqui está minha tentativa, não totalmente testada, mas parece fazer o que eu preciso.

/**
 * If given store code will reset only that store, otherwise will set all stores to "use default"
 *
 * If given product ids will reset only those products, otherwise all products will be set to "use default"
 *
 * @param $attributeCode
 * @param null $storeCode
 * @param null $productIds
 *
 */
public function forceProductsToUseDefault($attributeCode, $storeCode = null, $productIds = null)
{
    $conditions = array();

    if (is_null($storeCode)) {
        $conditions['store_id != ?'] = Mage_Core_Model_App::ADMIN_STORE_ID;
    } else {
        $store = Mage::app()->getStore($storeCode);
        if (!$store instanceof Mage_Core_Model_Store || !$store->getId()) {
            Mage::throwException("Store with code not found: $storeCode");
        }
        $conditions['store_id = ?' ] = $store->getId();
    }

    if (!is_null($productIds)) {
        $conditions['entity_id in(?)'] = $productIds;
    }

    $attribute = Mage::getModel('eav/entity_attribute')
        ->loadByCode(Mage_Catalog_Model_Product::ENTITY, $attributeCode);
    if (!$attribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract || !$attribute->getId()) {
        Mage::throwException("Attribute with code not found: $attributeCode");
    }
    $conditions['attribute_id = ?'] = $attribute->getId();

    $coreResource = Mage::getSingleton('core/resource');

    $coreResource->getConnection('core_write')->delete(
        $coreResource->getTableName(array('catalog/product', $attribute->getData('backend_type'))),
        $conditions
    );
}
Luke Rodgers
fonte
Por que estamos lançando um erro de sintaxe na linha 14? @Luke Rodgers
Complemento
Qual é o erro?
Lucas Rodgers
Está consertado agora, mas isso nunca é executado e finalizado corretamente no meu desenvolvedor. meio Ambiente. Alguma sugestão?
Suplemento
Não pode ajudar, sem o erro real :)
Luke Rodgers
algum guia sobre como devo usar esse código? posso usá-lo como um script independente?
Kris Wen
3

Você pode usar o evento core_block_abstract_to_html_before adminhtml para adicionar as caixas de seleção necessárias para cada atributo no formulário de atualização em massa do administrador.

protected $_controllers = array(
    'attribute', 
    'catalog_product_action_attribute'
    );


public function htmlBefore(Varien_Event_Observer $observer)
{
        $block = $observer->getBlock();

        if (!isset($block)) {
            return $this;
        }

        $request = Mage::app()->getRequest();
        $storeId = $request->getParam('store');

        if ($storeId != 0) {
            if(in_array($request->getControllerName(), $this->_controllers) 
                    && $request->getActionName() == 'edit') {
                // Add use_default checkboxes
                if ($block instanceof Mage_Adminhtml_Block_Catalog_Form_Renderer_Fieldset_Element) {
                    $block->getDataObject()->setId('empty');
                    $block->getDataObject()->setStoreId($storeId);
                    $block->getDataObject()->setExistsStoreValueFlag($block->getAttribute()->getAttributeCode());
                }
            }
        }
}

Em seguida, você precisaria usar o evento catalog_product_attribute_update_before para excluir os valores das tabelas EAV para uma visualização de loja específica, apenas para os atributos que possuem a caixa de seleção que você injetou anteriormente com core_block_abstract_to_html_before definido como marcado.

Espero que ajude.

Este módulo faz exatamente isso: http://mageinn.com/product/adminextra/ Também é possível redefinir o atributo ' url_key ' com esse módulo.

kolucciy
fonte