Magento EAV: как сложно удалить значение атрибута? - PullRequest
3 голосов
/ 29 декабря 2011

Давайте четко зададим вопрос, прежде чем вводить детали:


Есть ли способ сложно удалить атрибут значение из продукта?

Под сложно Я имею в виду удаление строки из базы данных, а не только установка значения на ноль или пустое значение.


Теперь подробности:

В настоящее время я столкнулся с проблемой в Magento.

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

Наш мешок продукт имеет только настраиваемый 1 атрибут: цвет .

Наш футболка продукт имеет 2 настраиваемых атрибута: цвет и tshirt_size .

Наше Платье Продукт имеет 2 настраиваемых атрибута: Цвет и Размер платья

Моя текущая проблема заключается в том, что когда я извлекаю свой продукт Bag из базы данных, атрибуты, хранящиеся в моем продукте: color , tshirt_size и dress_size .

Я подозреваю, что это потому, что в нашем магазине вы можете изменить набор атрибутов продукта (благодаря расширению сообщества FlagBit ChangeAttributeSet).

Я думаю, что продукт в сумке был создан с определенным набором атрибутов, затем кто-то изменил набор атрибутов на другой, а другой снова. Это привело бы к тому, что продукт получил ВСЕ атрибуты из ВСЕХ наборов атрибутов, на которые он был изменен. Но это всего лишь причина, и это может быть еще одна причина. На самом деле я в настоящее время не ищу конкретную причину, по которой у моего продукта были несвязанные атрибуты.

Я сегодня хочу сбросить моих продуктов. Под сбросом я подразумеваю удаление атрибутов, не связанных с моим продуктом. В случае с моей сумкой это означает удаление атрибутов tshirt_size и dress_size . И под удалением я имею в виду удалением навсегда этих атрибутов из объекта.

Моя проблема в том, что я не могу найти, как это сделать. Я попытался установить атрибуты в NULL и сохранить продукт, но когда я снова запрашиваю продукт, я все равно получаю атрибут в данных с нулевым значением. Я не хочу, чтобы значение атрибута было нулевым, я хочу, чтобы атрибут не существовал.

Вот пример кода, который немного объясняет то, что я пробовал:

$product = Mage::getModel('catalog/product')->load(1234); //Let's assume that my bag product ID is 1234

Mage::log($product->getData());

/* This last line dump all my products datas and contains among other things:

[...]=>...
[color]=>3
[tshirt_size]=>34
[dress_size]=>45
[...]=>...

*/

Если я сделаю:

$product->setData('tshirt_size',null);
$product->setData('dress_size',null);
$product->save();

затем еще раз:

$product = Mage::getModel('catalog/product')->load(1234);
 Mage::log($product->getData());

    /* I get:

    [...]=>...
    [color]=>3
    [tshirt_size]=>null
    [dress_size]=>null
    [...]=>...

    */

Я не хочу этого. Я хочу:

/*

[...]=>...
[color]=>3
[...]=>...

*/

Тот факт, что у меня все еще есть записи в моем массиве, означает, что фактические строки в базе данных не удаляются. Я хочу, чтобы строки были удалены.

Еще больше расстраивает, когда я делаю:

$product->getAttributes();

Он возвращает мне все атрибуты, которые могут быть установлены для моего продукта без несвязанных атрибутов - что имеет смысл, поскольку несвязанные атрибуты отсутствуют в наборе атрибутов моего продукта.

Итак, опять вопрос:

Есть ли способ сложно удалить атрибут значение из продукта?

По сложно Я имею в виду удаление строки из базы данных, а не только установка значения на ноль или пустое.

Спасибо за вашу помощь!

Хьюг.

К вашему сведению: я использую Magento 1.6.1.0 (но это ничего не меняет)

Ответы [ 7 ]

2 голосов
/ 10 ноября 2013

Мне, наконец, пришлось заняться этим, и хотя @vBuck был близок, я всегда мог запрашивать старые данные после переключения в наборе атрибутов, и если я переключился назад, я бы увидел старые данные, когда их не должно было быть.был там.Сегодня мне нужно убедиться, что случайные данные удалены.Вот как я подошел к этой теме.

Чтобы программно удалить атрибуты при переключении с одного набора на другой, сначала необходимо просмотреть все записи для нового набора, затем получить список всех атрибутов, проверитьпротив этого списка и (это важная часть) удалить его из правильной таблицы сущностей.Например, я хочу избавиться от значения 500 GB, которое есть в данных образца Magento, когда я переключаю Western Digital 500GB HD - 7200RPM с Hard Drive на Shoes.Для этого я должен удалить запись в таблице catalog_product_entity_text, в которой она хранится.Это означает, что я должен найти эту запись, где она равна идентификатору продукта, а затем удалить ее из таблицы типов сущностей.

Я смог это сделать и не смог найти случайные данные после.Это было подтверждено как поиском в БД, так и переключением на старый набор атрибутов и поиском данных.Вы можете найти все это здесь

https://gist.github.com/jeremyBass/6581038#file-attribute-clean-switch-md

ИСПЫТАНО в CE 1.7.0.2, 1.8.0.0

1 голос
/ 24 февраля 2013

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

Шаги:

  1. убедитесь, что в наборе attr есть значение attr.
  2. обновить все продукты с этим атрибутом, чтобы атрибут, нуждающийся в удалении, был равен нулю.
  3. удалить атрибут из набора

Кажется, когда я не очищаю все атрибуты до удаления атрибута из набора, в результате приложение оставляет там строки. Может быть, для безопасности, я не знаю, так как я не нырнул. То, что я могу сказать так же мало, как я видел в этом, это то, что если вы не очистите значения перед удалением attr из набора, когда вы устанавливаете attr к нулю, attr остается.

Итак, тогда программные решения должны будут следовать этой схеме. Если у меня будет время, я напишу его, но сейчас у меня в очереди 15 других задач.

0 голосов
/ 02 июля 2013

Похоже, это старый пост, но я тоже искал ответ здесь, и я думаю, что я нахожусь в решении.

Чтобы решить эту проблему, мне пришлось работать напрямую с адаптером записи ресурса продукта:

$product->getResource()->getWriteConnection()

чтобы удалить значения атрибута из таблицы.

Я получил подсказки о том, как это сделать после того, как перерыл какой-то код. См Mage_Catalog_Model_Resource_Eav_Mysql4_Abstract::_saveAttributeValue:

    $write   = $this->_getWriteAdapter();
    $storeId = Mage::app()->getStore($object->getStoreId())->getId();
    $table   = $attribute->getBackend()->getTable();

    /**
     * If we work in single store mode all values should be saved just
     * for default store id
     * In this case we clear all not default values
     */
    if (Mage::app()->isSingleStoreMode()) {
        $storeId = $this->getDefaultStoreId();
        $write->delete($table, join(' AND ', array(
            $write->quoteInto('attribute_id=?', $attribute->getAttributeId()),
            $write->quoteInto('entity_id=?', $object->getEntityId()),
            $write->quoteInto('store_id<>?', $storeId)
        )));
    }

Используя этот код в цикле по $product->getAttributes() перед изменением набора атрибутов, вы можете "отсоединить" значения от атрибутов продукта, не разрушая сами атрибуты. Затем вы можете безопасно изменить набор атрибутов (как это сделано в расширении Flagbit), не оставляя мертвых данных.

Используя приведенный выше код, вот демонстрация, которую я написал, чтобы доказать свою теорию:

$product=Mage::getModel('catalog/product')->load(MY_TARGET_PRODUCT_ID);
$write=$product->getResource()->getWriteConnection();

foreach($product->getAttributes() as $attribute) {
  if($attribute->getId()==MY_TARGET_ATTRIBUTE_ID) {
    $write->delete(
      $attribute->getBackend()->getTable(),
      join(' AND ', array(
        $write->quoteInto('attribute_id=?',$attribute->getAttributeId()),
        $write->quoteInto('entity_id=?',$product->getId())
      ))
    );
  }
}

В этом примере я ищу определенный атрибут, который нужно удалить из продукта, но вы можете удалить условное условие IF, чтобы удалить все вложенные значения.

Я не полностью проверил это, но пока все в порядке. Кстати, я использую Magento 1.4. Надеюсь, это кому-нибудь поможет!

UPDATE:

Похоже, вышеприведенное - только половина правильного Вы все равно должны быть осторожны, чтобы не очистить некоторые атрибуты, которые могут сделать продукт мертвым (например, имя, режим, состояние и другие). Так что в моем случае, похоже, мне придется сравнить с набором атрибутов по умолчанию перед удалением.

ДРУГОЕ ОБНОВЛЕНИЕ:

С помощью этого SO сообщения: https://stackoverflow.com/a/8500506/1442685 Мне удалось сравнить все атрибуты, связанные с продуктом, и удалить только значения не по умолчанию. Таким образом, меняя наборы, я могу гарантировать, что основная информация о продукте не будет потеряна. Ознакомьтесь с моим Gist для двух классов, которые делают все это:

https://gist.github.com/vbuck/5911170

0 голосов
/ 03 февраля 2013

После того, как вы связали набор атрибутов с продуктом, невозможно изменить набор атрибутов или удалить этот набор атрибутов.

Выход в том, чтобы экспортировать товар, а затем изменить лист и импортировать.

Эта ссылка также объясняет: https://collaborate.magento.com/magento/topics/how_do_i_change_product_attribute_set

0 голосов
/ 12 апреля 2012

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

или, может быть, вы предпочитаете такую ​​вещь?

class Mage_catalog_Model_Product_Attribute_Set_Api extends Mage_Api_Model_Resource_Abstract
{
 {
/**
 * Retrieve attribute set list
 *
 * @return array
 */
public function items()
{
    $entityType = Mage::getModel('catalog/product')->getResource()->getEntityType();
    $collection = Mage::getResourceModel('eav/entity_attribute_set_collection')
        ->setEntityTypeFilter($entityType->getId());

    $result = array();
    foreach ($collection as $attributeSet) {
        $result[] = array(
            'set_id' => $attributeSet->getId(),
            'name'   => $attributeSet->getAttributeSetName()
        );

    }

    return $result;
 }
} // Class Mage_Catalog_Model_Product_Attribute_Set_Api End
0 голосов
/ 03 января 2012

Вы должны иметь возможность сбросить значение, как любое из этих:

$product->unsetData('unwanted_attribute')
        ->save();

$product->unsUnwantedAttribute()
        ->save();
0 голосов
/ 30 декабря 2011

Хорошо, я наконец нашел его, через 15 минут после того, как задал вопрос (и потратил несколько часов на его решение)

Вот ответ:

$product = Mage::getModel('catalog/product')->load(1234); //Let's assume that my bag product ID is 1234
$product->setData('unwanted_attribute',null);    

$resource = $product->getResource();
$resource->saveAttribute($product,'unwanted_attribute');

Редактировать: это не работает. Если вы повторно сохраните продукт позже, выполнив команду $product->save(), все атрибуты появятся снова.

...