Pregunta

Mi tienda tiene aproximadamente 1000 productos y 600 paquetes, con vistas a unos 8 tiendas. Esto equivale a alrededor de 12.800 productos más o menos.

Vamos a ser la introducción de elementos configurables y uno de los atributos clave que desea volver a utilizar es una selección múltiple campo de formulario. Cada producto tiene un solo tipo seleccionado, por lo que el tipo de datos de back-end EAV que se configura durante la puesta en marcha de la tienda original en la elección errónea. En este punto nos gustaría migrar esta al tipo de datos desplegable.

¿Hay algún método relativamente indoloro para obtener esta instalado en la entrada de crear un atributo completamente nuevo, portar los datos, y la supresión de la antigua atr? Cualquier persona con alguna experiencia haciendo esto que me puede prestar un consejo útil?

¿Fue útil?

Solución

Usted no sólo tiene que cambiar el backend_type en la tabla eav_attribute, sino también copiar las filas de la fuente de la tabla de destino. Siguiente código le ayudará a lograr esto:

$connection         = _getConnection('core_write');
$attributeIds       = 'yourattributeid';
$entityTypeId       = 'oldentitytypeid;
$sql                = 'SELECT * FROM catalog_product_entity_varchar WHERE attribute_id IN ('.$attributeIds.') AND entity_type_id = '.$entityTypeId;
$rows               = $connection->fetchAll($sql);
foreach ($rows as $row){
    $price = $row['value'];
    if (!is_null($price)) {
        $sql = 'INSERT INTO catalog_product_entity_decimal (`entity_type_id`,`attribute_id`,`store_id`,`entity_id`,`value`)
            VALUES (?,?,?,?,?)';
        $connection->query($sql, array($row['entity_type_id'], $row['attribute_id'], $row['store_id'], $row['entity_id'], $price));
    }
    $sql = 'DELETE FROM catalog_product_entity_varchar WHERE value_id = ?'; // or your old storage table
    $connection->query($sql, $row['value_id']);
}
$sql = 'UPDATE eav_attribute SET backend_type="newbackendtype" WHERE attribute_id IN ('.$attributeIds.')';
$connection->query($sql);

Otros consejos

Esto se basa libremente en la respuesta de Tobias Zander, pero es un poco más robusto y cauteloso acerca de la actualización para que sea más seguro para ejecutarse en un entorno de producción. También se construyó expresamente para mover un multiselect a un select, (desplegable).

<?php

$installer = $this;
$installer->startSetup();
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');

$attributeCode = 'my_atribute';

/** @var Mage_Catalog_Model_Resource_Eav_Attribute $attribute */
$attribute = Mage::getModel('catalog/resource_eav_attribute') ->loadByCode(Mage_Catalog_Model_Product::ENTITY, $attributeCode);
$attributeId   = $attribute->getId();
$entityTypeId  = $setup->getEntityTypeId('catalog_product');

$connection    = $setup->getConnection('core_write');
$ea            = $setup->getTable('eav_attribute');
$cea            = $setup->getTable('catalog_eav_attribute');
$cpei          = $setup->getTable('catalog_product_entity_int');
$cpev          = $attribute->getBackendTable(); //$setup->getTable('catalog_product_entity_varchar');
$ip            = $setup->getTable('index_process');

/*
 * Sanity check on the existing attribute
 */
if ($attribute->getFrontendInput() != 'multiselect' || $attribute->getBackendType() != 'varchar') {
    Mage::throwException("Cannot migrate `{$attributeCode}`` because it is not the expected backend or frontend type.");
    return;
}

$connection->query("LOCK TABLES {$cpev} WRITE");

/*
 * Check that none of the entities in the database have multiple selected values
 */
$num = (int)$connection->fetchOne("
    SELECT COUNT(*) as num
    FROM {$cpev}
    WHERE ". $connection->prepareSqlCondition('attribute_id', $attributeId) ."
    AND ". $connection->prepareSqlCondition('entity_type_id', $entityTypeId) ."
    AND value LIKE '%,%'
");

if ($num !== 0) {
    $connection->query("UNLOCK TABLES");
    Mage::throwException("Cannot migrate `{$attributeCode}`` because it contains {$num} entities with multiple selected values.");
    return;
}

$connection->beginTransaction();

$connection->query("
    INSERT INTO {$cpei}
        (`entity_type_id`, `attribute_id`, `store_id`, `entity_id`, `value`)
    SELECT `entity_type_id`, `attribute_id`, `store_id`, `entity_id`, CONVERT(`value`,UNSIGNED INTEGER) as `value`
    FROM {$cpev}
    WHERE ". $connection->prepareSqlCondition('attribute_id', $attributeId) ."
    AND ". $connection->prepareSqlCondition('entity_type_id', $entityTypeId) ."
    AND value IS NOT NULL
    AND value != ''
");

$connection->query("
    UPDATE {$ea}
    SET
        `frontend_input`    = 'select',                             # from 'multiselect'
        `backend_type`      = 'int',                                # from 'varchar'
        `backend_model`     = NULL,                                 # from 'eav/entity_attribute_backend_array'
        `source_model`      = 'eav/entity_attribute_source_table'   # from NULL
    WHERE ". $connection->prepareSqlCondition('attribute_id', $attributeId) ."
");

/*
 * OPTIONAL: Migrate the new attribute to be a configurable attribute
 */
$connection->query("
    UPDATE {$cea}
    SET `is_configurable` = '1'
    WHERE ". $connection->prepareSqlCondition('attribute_id', $attributeId) ."
");

$connection->query("UNLOCK TABLES");

$connection->query("
    DELETE
    FROM {$cpev}
    WHERE ". $connection->prepareSqlCondition('attribute_id', $attributeId) ."
    AND ". $connection->prepareSqlCondition('entity_type_id', $entityTypeId) ."
");

$connection->query("
    UPDATE {$ip}
    SET `status` = 'require_reindex'
    WHERE `indexer_code` IN ('catalog_product_attribute', 'catalog_product_flat')
");

$connection->commit();

$installer->endSetup();

He actualizado el código de Tyler V. que se utiliza directamente en la base de datos y para Magento 2.2.7. El mayor cambio es que entity_type_id no se utiliza en las tablas de base de datos actual.

También creé el nuevo atributo súper manualmente a través del panel de control de administración de Magento. Lo nombré el mismo que el anterior pero adjuntas "nuevo" hasta el final. Voy a eliminar el atributo de selección múltiple de edad al final, cuando he acabado y cambiar el nombre de la nueva lista desplegable para el nombre de la antigua.

Para crear el nuevo atributo súper, acceder a su panel de control del administrador y haga clic en Almacenes> Atributos> los productos. Añadir nuevo atributo. Asegúrese de alcance es global y el tipo de entrada Catolog es desplegable. A continuación, vaya a las tiendas> Atributos> conjunto de atributos y arrastre el nuevo atributo a su conjunto de atributos.

Mi viejo attribute_id multiselect es 144. Mi nuevo attribute_id desplegable es 278. Usted tendrá que cambiar éstos a sus números de identificación correspondientes.

  1. Compruebe si los viejos valores de selección múltiple que tienen más de un valor (tiene que ser uno-a-uno para el menú desplegable). O bien cambiar los dos para tener un nuevo delimitador que no sea una coma para que puedan permanecer como sus propios valores nuevos o dividirlas en valores individuales.

* SELECT FROM catalog_product_entity_varchar DONDE attribute_id = 144 y el valor LIKE '%,%'

  1. Copiar valores varchar a la mesa int, ignorando los valores vacíos y valores múltiples.

INSERT INTO catalog_product_entity_int (attribute_id, store_id, entity_id, value) SELECT '278' como attribute_id, store_id, entity_id, CONVERT (value, entero sin signo) como value DE catalog_product_entity_varchar DONDE attribute_id = 144 y el valor no es nulo y sin valor! = '' Y el valor NOT LIKE '%,%'

  1. Cambiar attribute_id de viejo a nuevo en la tabla eav_attribute_option.

ACTUALIZACIÓN eav_attribute_option SET attribute_id = 278 DONDE attribute_id = 144

  1. Reindex (de la CLI: php bin / magento indexador: reindex) y Borrar caché (de la CLI: php bin / magento caché: limpio). A continuación, vaya a las tiendas> Atributos> Productos y haga clic en el nuevo atributo. Asegúrese de que los viejos valores se encuentran ahora en el nuevo atributo.

  2. Eliminar el atributo de selección múltiple de edad y cambiar el nombre de la nueva para el nombre de la antigua.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a magento.stackexchange
scroll top