Измените тип внутреннего атрибута с множественного выбора на выпадающий

magento.stackexchange https://magento.stackexchange.com/questions/500

Вопрос

В моем магазине представлено примерно 1000 товаров и 600 комплектов, с примерно 8 просмотрами в магазине.Это эквивалентно примерно 12 800 продуктам или около того.

Мы собираемся представить конфигурируемые файлы, и одним из ключевых атрибутов, которые мы хотим использовать повторно, является поле формы с несколькими вариантами выбора.Для каждого продукта выбран только один тип, поэтому внутренний тип данных EAV, который был настроен при настройке исходного магазина, был выбран неправильно.На данном этапе мы хотели бы перенести это в выпадающий тип данных.

Есть ли какой-либо относительно безболезненный метод для этой настройки, помимо создания совершенно нового атрибута, переноса данных и удаления старого attr?Кто-нибудь, у кого есть какой-либо опыт в этом, кто может дать мне несколько полезных советов?

Это было полезно?

Решение

Вам нужно не только изменить backend_type в таблице eav_attribute, но и скопировать строки из таблицы источника на целевой. Следующий код поможет вам сделать это:

$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);

Другие советы

Это свободно основано на ответе Тобиаса Зандера, но немного более надежно и осторожно в отношении обновления, так что безопаснее работать в производственной среде. Он также явно построен для перемещения multiselect в select, (падать.)

<?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();

Я обновил код Тайлера В. для использования непосредственно в базе данных и для Magento 2.2.7.Самое большое изменение заключается в том, что entity_type_id не используется в текущих таблицах базы данных.

Я также создал новый атрибут super вручную через панель администрирования Magento.Я назвал его так же, как и старый, но добавил "новый" в конце.Я удалю старый атрибут multiselect в конце, когда закончу, и переименую новый выпадающий список на имя старого.

Чтобы создать новый супер-атрибут, войдите в панель управления администратора и выберите Магазины > Атрибуты> Продукты.Добавьте новый атрибут.Убедитесь, что область видимости глобальная, а тип ввода Catolog - выпадающий.Затем перейдите в Магазины> Атрибуты> Набор атрибутов и перетащите новый атрибут в свой набор атрибутов.

Мой старый многовыборный attribute_id равен 144.Мой новый выпадающий attribute_id равен 278.Вам нужно будет сменить их на соответствующие вам идентификационные номера.

  1. Проверьте, не используются ли старые значения multiselect, которые имеют более одного значения (должно быть взаимно однозначным для выпадающего списка).Либо измените их, чтобы они имели новый разделитель, отличный от запятой, чтобы они могли оставаться своими собственными новыми значениями, либо разделите их на отдельные значения.

ВЫБЕРИТЕ * ИЗ catalog_product_entity_varchar, ГДЕ attribute_id = 144 И значение ТИПА '%,%'

  1. Скопируйте значения varchar в таблицу int, игнорируя пустые значения и несколько значений.

ВСТАВИТЬ В каталог_product_entity_int (attribute_id, store_id, entity_id, value) ВЫБЕРИТЕ "278" в качестве attribute_id, store_id, entity_id, ПРЕОБРАЗОВАТЬ(value, ЦЕЛОЕ ЧИСЛО БЕЗ ЗНАКА) как value ИЗ catalog_product_entity_varchar ГДЕ attribute_id = 144 И значение НЕ РАВНО НУЛЮ, А value!= " И значение НЕ ПОХОЖЕ НА '%,%'

  1. Измените attribute_id со старого на новый в таблице eav_attribute_option.

ОБНОВИТЬ параметр eav_attribute_option, УСТАНОВИТЬ attribute_id = 278, ГДЕ attribute_id = 144

  1. Переиндексация (из CLI:php bin / magento indexer: переиндексация) и Очистить кэш (из CLI:кэш php bin / magento: очистить).Затем перейдите в Магазины > Атрибуты> Товары и нажмите на свой новый атрибут.Убедитесь, что старые значения теперь отображаются в новом атрибуте.

  2. Удалите старый атрибут multiselect и переименуйте новый атрибут в старое имя.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с magento.stackexchange
scroll top