Magento changing attribute type in backend
Asked Answered
Z

5

10

is it possible to change type of a attribute after it has been created. I want to change type of certain attribute to Multi select list. Type of these attribute is currently 'Dropdown'. Actually When I create the attributes, there was no need of multi select when I created it originally, but, now client wants to change it to "Multi select".

Please help me out, I can not create new attributes by deleting the old ones, as, there is some data, and certain part of design is hard coded and depends on certain values of attribute.

Zwick answered 21/10, 2011 at 12:42 Comment(0)
G
17

Yes it's possible programmatically thanks to the method Mage_Eav_Model_Entity_Setup::updateAttribute($entityTypeId, $id, $field, $value=null, $sortOrder=null)

It's not possible with the Attribute Management in Magento Backend because it has consequence with the existing data. In your case, changing from select to multiselect should be ok but do a database backup and test if your product are still correctly displayed.

Programmatically, the best way is to do it from an update setup script. I don't know your module but here are some information to do it.

An update setup script is launched when you provide a new number version to your module and you provide a setup script with the old and new version number as a filename.

1) Here is the header of a config.xml module, change it to provide a higher version. For example, the new version is

<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
    <Mycompany_Mymodule>
        <version>1.0.1</version><!-- the old one was 1.0.0 -->
    </Mycompany_Mymodule>
</modules>
...
</config>

2) you need to have in the config.xml file, between the tags <global>...</global> the following code, please adapt to your situation:

  <resources>
        <mymodule_setup><!-- name that you will give to the folder into the sql folder  -->
            <setup>
                <module>Mycompany_Mymodule</module>
                <class>Mage_Eav_Model_Entity_Setup</class><!-- You can have a setup class which extends this class -->
            </setup>
            <connection>
                <use>default_setup</use>
            </connection>
        </mymodule_setup>
    </resources>

3) Then you need to create a setup script in your module folder with the old and new version number app/code/local/mycompany/mymodule/sql/mymodule_setup/mysql4-upgrade-1.0.0-1.0.1.php (mysql4-upgrade-old.version.number-new.version.number.php)

4) And in this new script set a code like this, please adapt to your situation:

<?php
$installer = $this;
/*@var $installer Mage_Eav_Model_Entity_Setup */

$entityTypeId = $installer->getEntityTypeId('catalog_product');

$idAttributeOldSelect = $this->getAttribute($entityTypeId, 'myold_attribute', 'attribute_id');
$installer->updateAttribute($entityTypeId, $idAttributeOldSelect, array(
    'frontend_input'    => 'multiselect'
));

5) Refresh your Magento page and eventually flush your cache

Granjon answered 21/10, 2011 at 14:3 Comment(5)
@mushin is right. You want 'frontend_input' in the updateAttribute() call, not 'input'. (Tested on Magento 1.9.0.1)Headlight
@TylerV. if you check the class Mage_Eav_Model_Entity_Setup::_prepareValues you will see that input will workConquer
@SylvainRayé That method will accept input and change it to frontend_input for you. However, Mage_Eav_Model_Entity_Setup::_prepareValues is only called by Mage_Eav_Model_Entity_Setup::addAttribute and not Mage_Eav_Model_Entity_Setup::updateAttribute (or it's protected counterpart) which you use in step 4 of your instructions.Headlight
are you kidding me. magento is a pos.Dincolo
I tried the above one but not working for me here is my config.xml:Uptown
M
6

4.I think update uses database fields, i.e input should frontend_input.

<?php
$installer = $this;
/*@var $installer Mage_Eav_Model_Entity_Setup */

$entityTypeId = $installer->getEntityTypeId('catalog_product');

$idAttributeOldSelect = $this->getAttribute($entityTypeId, 'myold_attribute', 'attribute_id');
$installer->updateAttribute($entityTypeId, $idAttributeOldSelect, array(
    'frontend_input' => 'multiselect'
));
Michelsen answered 12/8, 2013 at 14:22 Comment(1)
When following this I also had to set 'backend_type' => 'varchar', 'backend_model' => 'eav/entity_attribute_backend_array'Vena
A
2

First you need to update the attribute input type to multiselect using the below-mentioned code:

UPDATE eav_attribute SET
entity_type_id = '4',
attribute_model = NULL,
backend_model = 'eav/entity_attribute_backend_array',
backend_type = 'varchar',
backend_table = NULL,
frontend_model = NULL,
frontend_input = 'multiselect',
frontend_class = NULL
WHERE attribute_id = 'YOUR_ATTRIBUTE_ID_HERE';

Now, copy the attribute values from the old table to the new:

INSERT INTO catalog_product_entity_varchar ( entity_type_id, attribute_id, store_id, entity_id, value)
SELECT entity_type_id, attribute_id, store_id, entity_id, value
FROM catalog_product_entity_int
WHERE attribute_id = YOUR_ATTRIBUTE_ID_HERE;

Finally, remove the old values otherwise they will conflict with the new setup (the old values will load, but Magento will save new values to the varchar table):

DELETE FROM catalog_product_entity_int
WHERE entity_type_id = 4 and attribute_id = YOUR_ATTRIBUTE_ID_HERE;
Airburst answered 30/11, 2016 at 11:49 Comment(0)
P
1

I created and tested a script on M1 1.9.4.3 based on the top answer in this question as well as this one:

// Get the attribute codes that we want to update
$attributeCodes = $this->getAttributeCodesToChange();

$this->log('The following attributes will be changed from select to multiselect: %s %s', "\n\n", print_r($attributeCodes, true));

if (count($attributeCodes)) {

    // Prepare the DB connection
    $setup = new Mage_Eav_Model_Entity_Setup('core_setup');
    $connection = $setup->getConnection('core_write');
    $eavAttributeTable = $setup->getTable('eav_attribute');
    $catalogProductEntityIntTable = $setup->getTable('catalog_product_entity_int');
    $catalogProductEntityVarcharTable = $setup->getTable('catalog_product_entity_varchar');
    $entityTypeId = $entityTypeId  = $setup->getEntityTypeId('catalog_product');

    // Loop through the attribute codes, update each attribute
    foreach ($attributeCodes as $attributeId => $attributeCode) {

        // Change the type of the attribute itself
        $connection->query("
            UPDATE {$eavAttributeTable}
            SET
                `frontend_input` = 'multiselect',
                `frontend_model` = NULL,
                `frontend_class` = NULL,
                `backend_type` = 'varchar',
                `backend_model` = 'eav/entity_attribute_backend_array',
                `backend_table` = NULL,
                `attribute_model` = NULL,
                `source_model` = NULL
            WHERE ". $connection->prepareSqlCondition('attribute_id', $attributeId)
        );

        // Insert the current values of the attribute into the table where the multiselect attribute requires them
        $connection->query("
            INSERT INTO {$catalogProductEntityVarcharTable} (`entity_type_id`, `attribute_id`, `store_id`, `entity_id`, `value`)
            SELECT `entity_type_id`, `attribute_id`, `store_id`, `entity_id`, `value`
            FROM {$catalogProductEntityIntTable}
            WHERE ". $connection->prepareSqlCondition('attribute_id', $attributeId) ."
            AND ". $connection->prepareSqlCondition('entity_type_id', $entityTypeId) ."
            AND value IS NOT NULL
            AND value != ''
        ");

        // Remove the values from the table where the select attribute stored them
        $connection->query("
            DELETE FROM {$catalogProductEntityIntTable}
            WHERE " . $connection->prepareSqlCondition('entity_type_id', $entityTypeId) . "
            AND " . $connection->prepareSqlCondition('attribute_id', $attributeId)
        );

        $this->log('Successfully changed attribute type for attribute: ' . $attributeCode);
    }
}

$this->log('Finished!');
Prasad answered 15/9, 2022 at 6:15 Comment(0)
D
0

You can try Mage_Eav_Model_Entity_Setup::updateAttribute method.

Deliladelilah answered 21/10, 2011 at 13:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.