Magento EAV:如何硬删除属性值?

时间:2011-12-29 19:47:45

标签: magento magento-1.4 magento-1.5 entity-attribute-value

在进入细节之前,让我们清楚地提出问题:


是否有 从产品中删除属性的方法?

通过 hard 我的意思是,从数据库中删除行,而不仅仅是将值设置为null或为空。


现在,详细信息:

我目前面临着Magento的问题。

我商店中的许多产品都具有与产品无关的用户定义属性。例如,我们假设我们有一个 bag 产品,以及其他产品,如 T恤,连衣裙,裤子等:

我们的产品只有可配置的1个属性:颜色

我们的 T恤产品有2个可配置属性:颜色 tshirt_size

我们的连衣裙产品有2个可配置属性:颜色 dress_size

我目前的问题是,当我从数据库中检索 Bag 产品时,我产品中存储的属性为:颜色 tshirt_size dress_size

我怀疑这是因为在我们的商店中您可以更改产品的属性集(感谢FlagBit ChangeAttributeSet社区扩展)。

我认为包产品是使用特定的属性集创建的,然后有人将属性集更改为另一个,另一个更改。这将导致产品从所有已更改的属性集中获取所有属性。但这仅仅是一个,而这可能是另一个原因。我实际上目前没有找到导致我的产品具有不相关属性的具体原因。

我今天想重置我的产品。通过重置我的意思是删除与我的产品无关的属性。对于我的 bag ,这意味着删除 tshirt_size dress_size 属性。通过删除,我的意思是从对象中永久删除这些属性。

我的问题是,我无法找到如何做到这一点。我尝试将属性设置为NULL并保存产品,但是当我再次查询产品时,我仍然获得数据中的属性,其值为null。我不希望属性值为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();

它返回了我可以设置到我的产品的所有属性没有不相关的属性 - 这是有道理的,因为不相关的属性不在我的产品的属性集中。

所以,问题是:

是否有 从产品中删除属性的方法?

通过 hard 我的意思是,从数据库中删除行,而不仅仅是将值设置为null或为空。

感谢您的帮助!

雨果。

仅供参考:我使用Magento 1.6.1.0(但它并没有真正改变任何东西)

7 个答案:

答案 0 :(得分:2)

我最终不得不解决这个问题,虽然@vBuck很接近,但我总是可以在属性集中切换后查询旧数据,如果我切换回来,我会看到旧数据时它不应该是我去过那儿。今天,我同样需要确保删除随机数据。以下是我如何处理这个话题。

为了在从一个集合切换到另一个集合时以编程方式删除属性,您必须首先查看新集合的所有条目,然后获取所有属性的列表,检查该列表并且(这是重要部分)从正确的实体表中删除它。例如,当我将500 GBWestern Digital 500GB HD - 7200RPM切换到Hard Drive时,我希望摆脱示例Magento数据中Shoes的值。为此,我必须删除它所存储的catalog_product_entity_text表中的条目。这意味着我必须找到与产品ID相等的条目,然后将其从其实体类型表中删除。

我能够做到这一点,之后无法找到迷路数据。数据库搜索和切换回旧属性集并查找数据都证实了这一点。你可以在这里找到它

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

在CE 1.7.0.2,1.8.0.0

中测试

答案 1 :(得分:1)

所以我也很想得到程序化的答案,但我没有时间去做。但这是我可以为这个链提供的。当您尝试从管理员中删除属性时,您会看到所需的结果操作。

<强>步骤:

  1. 确保attr集在其设置中包含attr。
  2. 使用该attr设置更新所有产品,使attr需要删除为null。
  3. 从集合中移除attr
  4. 似乎当我从集合中移除attr之前没有清除所有的attrs时,结果是应用程序将行留在那里。也许是为了安全起见,我不知道,因为我没有潜入。我可以告诉我的是,如果你没有清除attr从集合中移除之前的值,当你设置attr为null,attr仍然存在。

    那么,程序化解决方案将需要遵循这种模式。如果我有时间,我会写它,但我现在已经在队列中完成了15个其他任务。

答案 2 :(得分:0)

好的,我终于在提问后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()重新保存产品,则会重新显示所有属性。

答案 3 :(得分:0)

看起来这是一篇旧帖子,但我也在寻找答案,我想我已经找到了解决方案。

要解决这个问题,我必须直接使用产品资源的写适配器:

$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。希望它可以帮助别人!

<强>更新

看起来上面只有一半是正确的。您仍然必须小心不要清除可能导致产品死亡的某些属性(例如名称,模式,状态等)。所以在我的情况下,看起来我必须在删除之前与默认属性集进行比较。

另一个更新:

在此SO帖子的帮助下:https://stackoverflow.com/a/8500506/1442685 我能够比较链接到产品的所有属性,并仅删除非默认值。这样,在更改集合时,我可以确保不会丢失有关产品的基本信息。查看我的Gist,了解这两个课程的完成情况:

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

答案 4 :(得分:-1)

你应该可以像以下任何一个一样取消设置值:

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

$product->unsUnwantedAttribute()
        ->save();

答案 5 :(得分:-1)

您需要转到管理员&gt;&gt;目录&gt;&gt;属性&gt;&gt;管理属性集 如果您尝试管理产品目录,则应首先考虑您的属性(与您的产品分开),然后再考虑您的产品(实际上并不是产品的一部分)。 正确建立属性和属性集后,可以将它们应用于具有每个属性值的产品。

或者您更喜欢这种事情?

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

答案 6 :(得分:-3)

将属性集关联到产品后,无法更改属性集或删除该属性集。

出路是导出产品然后修改工作表并导入。

此链接还说明: https://collaborate.magento.com/magento/topics/how_do_i_change_product_attribute_set