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

发布于 2024-12-23 04:29:56 字数 2414 浏览 1 评论 0原文

在进入细节之前,让我们先问清楚一个问题:


有没有办法从产品中删除属性

我所说的“硬”是指从数据库中删除该行,而不仅仅是将值设置为 null 或空。


现在,详细信息:

我目前在 Magento 上遇到一个问题。

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

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

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

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

我当前的问题是,当我取回我的Bag产品时从数据库中,我的产品中存储的属性是:颜色tshirt_sizedress_size

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

我认为袋子产品是用特定的属性集创建的,然后有人将属性集更改为另一个,然后又更改了另一个。这将导致产品从其已更改为的所有属性集中获取所有属性。但这只是一个原因,可能还有其他原因。实际上,我目前并没有寻找导致我的产品具有不相关属性的具体原因。

我今天想要重置我的产品。我所说的重置是指删除与我的产品无关的属性。就我的包而言,这意味着删除 tshirt_sizedress_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
[...]=>...

*/

如果我执行 a:

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

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

因此,问题再次出现:

是否有办法从产品中删除属性

我所说的“硬”是指从数据库中删除该行,而不仅仅是将值设置为 null 或空。

感谢您的帮助!

胡格斯.

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

Let's ask the question clearly before entering into the details:


Is there a way of hard deleting an attribute value from a product?

By hard I mean, removing the row from the database and not only setting the value to null or empty.


Now, the details:

I'm currently confronted to a problem on Magento.

Many product in my store have user defined attributes that are not related to the product. For example, let's say we have a bag product, among other products like t-shirts,dresses,pants,etc.:

Our bag product has only configurable 1 attribute: color.

Our T-Shirt product has 2 configurable attributes: color and tshirt_size.

Our Dress product has 2 configurable attributes: color and dress_size

My current problem is that when I retrieve my Bag product from the database, the attributes stored in my product are: color, tshirt_size and dress_size.

I suspect that it is because on our store you can change the attribute set of a product (thanks to the FlagBit ChangeAttributeSet community extension).

I think that the bag product has been created with a specific attribute set, then someone changed the attribute set to another, and another again. That would have lead the product to get ALL the attributes from ALL the attribute sets it has been changed to. But that's just a though, and it could be another reason. I'm actually currently not looking for the specific reason that led my product to have unrelated attributes.

I today want to reset my products. By reset I mean removing the attributes unrelated to my product. In the case of my bag, that means removing the tshirt_size and dress_size attributes. And by removing I mean deleting forever these attributes from the object.

My problem is that, I can't find how to do it. I tried setting the attributes to NULL and saving the product, but when I query again the product, I still get the attribute in the datas, with a null value. I don't want the attribute value to be null, I want the attribute to not exist.

Here is a sample of code that explains a bit what I tried:

$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
[...]=>...

*/

If I do a:

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

then again:

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

    /* I get:

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

    */

I don't want that. I want:

/*

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

*/

The fact that I still have the entries in my array mean that the actual rows in the database are not deleted. I want the rows to be deleted.

Even more frustrating, when I do a:

$product->getAttributes();

It returns me all the attributes that can be set to my product without the unrelated attributes -which makes sense because the unrelated attributes are not in the attribute set of my product.

So, again, the question is:

Is there a way of hard deleting an attribute value from a product?

By hard I mean, removing the row from the database and not only setting the value to null or empty.

Thanks for your help!

Hugues.

FYI: I'm using Magento 1.6.1.0 (but it does not really change anything)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

平定天下 2024-12-30 04:29:57

我终于不得不解决这个问题,虽然@vBuck很接近,但我总是能够在属性集中切换后查询旧数据,如果我切换回来,我会看到不应该存在的旧数据。今天,我有同样的需要确保随机数据被删除。以下是我处理这个话题的方法。

为了在从一个集合切换到另一个集合时以编程方式删除属性,您必须首先查看新集合的所有条目,然后获取所有属性的列表,检查该列表并(这是重要的部分)将其从正确的实体表。例如,当我从 硬盘切换 Western Digital 500GB HD - 7200RPM 时,我想删除示例 Magento 数据中的 500 GB鞋子。为此,我必须删除存储它的 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

I finally had to tackle this, and although @vBuck was close, I always was able to query the old data after the switch in the attribute set and if I switched back I would see the old data when it shouldn't have been there. Today, I have the same need to ensure the random data is removed. Here is how I approached this topic.

In order to programmatically delete attributes when you switch from one set to another you must first look at all the entries for the new set, then get a list of all attributes, check against that list and (this is the important part) remove it from the correct entity table. For example, I want to get rid of a value of 500 GB that is in the sample Magento data when I switch Western Digital 500GB HD - 7200RPM from Hard Drive to Shoes. In order to do that I must remove the entry in the catalog_product_entity_text table it's stored at. This means that I must find that entry where it's equal to the product id and then delete it from it's entity type table.

I was able to do this, and was not able to find the stray data after. This was confirmed by both a DB search and switching back to the old attribute set and looking for the data. you can find it all here

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

TESTED in CE 1.7.0.2, 1.8.0.0

云仙小弟 2024-12-30 04:29:57

所以我也很想得到程序化的答案,但我没有时间这样做。但这就是我能为这个连锁店提供的。当您尝试从管理中自行删除属性时,您会看到所需的结果操作发生。

步骤

  1. 确保 attr 集中包含 attr。
  2. 更新具有该属性集的所有产品,将需要删除的属性设置为空。
  3. 从集合中删除 attr

似乎当我在从集合中删除 attr 之前没有清除所有 attr 时,结果是应用程序将行保留在那里。也许是为了安全起见,我不知道,因为我还没有深入研究。据我所知,如果您在从集合中删除 attr 之前没有清除这些值,那么当您设置attr 为 null,attr 保留。

因此,程序化解决方案将需要遵循该模式。如果我有时间我会写它,但现在我还有大约 15 个其他任务在队列中。

So I too would love to have the programmatic answer, but I don't have the time to do it. But this is what I can provide to this chain. You see the desired resulting action happening when you try to remove an attribute by its self from the admin.

Steps:

  1. make sure the attr set has the attr in it's set.
  2. update all products with that attr set to have the attr needing deletion as null.
  3. remove the the attr from the set

Seems when I don't clear all attrs before removal of attr from the set, the result is for the app to leave the rows there. Maybe for safety, I don't know as I have not dived in. What I can tell with as little as I have looked in this it’s that if you don't clear the values before attr removal from the set, when you set the attr to null, the attr remains.

So, then the programmatic solutions will need to follow that pattern. If I get time I'll write it, but I have like 15 other tasks in the queue right now.

嘴硬脾气大 2024-12-30 04:29:57

好的,我终于找到了它,在提出问题 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() 重新保存产品,所有属性都会重新出现。

Ok, I found it finally, 15 minutes after asking the question (and spending few hours trying to solve it)

Here is the answer:

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

Edit: This doesn't work. If you re-save the product later by doing a $product->save(), all the attributes reappear.

梦里泪两行 2024-12-30 04:29:57

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

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

$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
我能够比较与产品相关的所有属性并仅删除非默认值。这样,在换套时,我可以确保产品的基本信息不会丢失。查看我的要点,了解使这一切发生的两个类:

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

Looks like this is an old post, but I too was looking for an answer here, and I think I'm onto a solution.

To solve this, I had to work directly with the product resource's write adapter:

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

to delete the attribute values from the table.

I got clues on how to do this after digging through some code. See 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)
        )));
    }

By using this code in a loop through $product->getAttributes() before changing the attribute set, you are able to "unlink" the values from the attributes of the product without destroying the attributes themselves. Then you can change the attribute set (as done in Flagbit's extension) safely, not leaving behind dead data.

Using the above code, here's a demonstration that I've written to prove my theory:

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

In this example, I'm looking for a specific attribute to clear from the product, but you can remove the IF conditional to delete every attached value.

I haven't fully tested this, but so far it seems alright. I'm running Magento 1.4, by the way. Hope it helps someone!

UPDATE:

Looks like the above is only half correct. You'll still have to be careful not to clear certain attributes that might render the product dead (such as the name, mode, status, and others). So in my case, it looks like I'll have to compare with the default attribute set before removing.

ANOTHER UPDATE:

With the help of this SO post: https://stackoverflow.com/a/8500506/1442685
I was able to compare all attributes linked to a product and delete only the non-default values. This way, when changing sets, I can ensure that basic information about the product is not lost. Check out my Gist for the two classes which make it all happen:

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

奶气 2024-12-30 04:29:57

您应该能够像以下任一方式取消设置该值:

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

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

You should be able to unset the value like either of these:

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

$product->unsUnwantedAttribute()
        ->save();
红尘作伴 2024-12-30 04:29:57

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

或者也许你更喜欢这种东西?

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

you need to go to admin>>catalog>>attributes>>manage attribute sets
if your trying to manage your product catalog you should first think of your attributes (separate to your product), then your sets(again not actually part of your products).
after you have properly established your attributes and sets (of attributes) you can apply them to products with values for each attribute.

or maybe you prefer this kinda thing?

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
天涯沦落人 2024-12-30 04:29:57

一旦将属性集与产品相关联,就无法更改属性集或删除该属性集。

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

此链接还解释了:
https://collaborate.magento.com/magento/topics/how_do_i_change_product_attribute_set

Once you have associated an attribute set to a product there is no way to change attribute set or remove that attribute set.

The way out is to export product and then modify sheet and import.

This link also explains :
https://collaborate.magento.com/magento/topics/how_do_i_change_product_attribute_set

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文