バックエンド属性タイプをマルチセレクトからドロップダウンに変更します
-
16-10-2019 - |
質問
私の店には約1000の製品と600のバンドルがあり、約8つの店舗ビューがあります。これは、約12,800個の製品に相当します。
Configurablesを導入する予定です。再利用する重要な属性の1つは、マルチセレクトフォームフィールドです。すべての製品には選択されたタイプが1つしかないため、元のストアのセットアップ中に構成されたEAVバックエンドデータタイプは誤って選択されました。この時点で、これをドロップダウンデータ型に移行したいと思います。
これをまったく新しい属性を作成し、データを移植し、古い属性を削除することから、これをセットアップするための比較的痛みのない方法はありますか?これをしている経験がある人は、私に有益なアドバイスを貸すことができますか?
解決
eav_attributeテーブルのbackend_typeを変更するだけでなく、ソースからターゲットテーブルに行をコピーする必要があります。次のコードは、これを達成するのに役立ちます。
$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();
Tyler V.のコードをデータベースで直接使用し、Magento 2.2.7で使用しました。最大の変更は、Entity_Type_IDが現在のデータベーステーブルでは使用されていないことです。
また、Magento Admin Dashboardを介して新しいスーパー属性を手動で作成しました。私はそれを古いものと同じように命名しましたが、最後まで「新しい」を追加しました。最後に古いマルチセレクト属性を削除し、新しいドロップダウンを古い名前の名前に変更します。
新しいスーパー属性を作成するには、管理ダッシュボードにログインし、[ストア]> [属性]> [属性]をクリックします。新しい属性を追加します。 Scopeがグローバルであり、Catolog入力タイプがドロップダウンであることを確認してください。次に、Stores> attributes>属性セットに移動し、新しい属性を属性セットにドラッグします。
私の古いマルチセレクト属性_IDは144です。私の新しいドロップダウン属性_IDは278です。これらを適切なID番号に変更する必要があります。
- 複数の値を持つ古いマルチセレクト値があるかどうかを確認します(ドロップダウンの場合は1対1である必要があります)。これらを変更して、コンマ以外の新しいデリミターを持つように変更して、自分の新しい値としてとどまるか、個々の値に分割することができます。
select * from catalog_product_entity_varcharwhere where artibute_id = 144および '%、%'のような値
- 空の値と複数の値を無視して、varchar値をintテーブルにコピーします。
catalog_product_entity_intに挿入(attribute_id
, store_id
, entity_id
, value
)「278」を選択します attribute_id
, store_id
, entity_id
、 変換(value
、署名されていない整数)as value
catalog_product_entity_varcharから属性_id= 144で、値はnullとvalue!= ''ではなく、 '%、%'のようではありません
- eav_attribute_optionテーブルで属性_idを古いものから新しいものに変更します。
更新eav_attribute_option set attribute_id = 278ここで属性_id= 144
Reindex(CLIから:PHP Bin/Magento Indencer:Reindex)およびClear Cache(CLI:PHP Bin/Magento Cache:Clean)。次に、Stores> Attributes>製品に移動し、新しい属性をクリックします。古い値が新しい属性に表示されていることを確認してください。
古いマルチセレクト属性を削除し、新しいものを古い名前の名前に変更します。