草庐IT

php - Magento - 修改产品属性后重新分配目录规则

coder 2024-04-20 原文

我正在为 Magento 1.5.1.0 开发一个扩展,它允许我为库存数量减少到零的产品添加目录价格规则。我在我的属性集中添加了一个名为 auto_discount_active 的属性。此属性是我的开/关开关,用作我的价格规则的条件。

我编写了一个 Observer,它对事件 sales_order_place_aftercatalog_product_save_before 使用react。它的任务是检查当前产品的库存数量是否已更改,并将我的自定义属性设置为打开或关闭。

处理 catalog_product_save_before 事件的方法工作正常。在后端保存一篇文章后,价格规则会像它应该的那样变得(不)活跃。代码如下所示:

class Company_AutoDiscount_Model_Observer
{
  public function updateAutoDiscount($observer)
  {
    /**
     * @var Varien_Event
     */
    $event     = $observer->getEvent();

    $product    = $event->getProduct();
    $data       = $product->getStockData(); 

    $discount   = $data['qty'] < 1 ? true : false;
    $attributes = $product->getAttributes();
    $attribute  = $attributes["auto_discount_active"];

    if ($product->getAutoDiscountAllowed())
    {
        $product->setAutoDiscountActive($discount);
    }

    return $this;
  }
}

现在我想做同样的事情,如果有人在我的商店下订单。因为我使用了到目前为止有效的事件 sales_order_place_after。但是更改自定义属性值后,价格规则没有更新。我的观察者方法如下所示:

public function updateAutoDiscountAfterOrder($observer)
{
    /**
     * @var Varien_Event
     */
    $event      = $observer->getEvent();
    $order      = $event->getOrder();

    foreach ($order->getItemsCollection() as $item) 
    {
        $productId  = $item->getProductId();
        $productIds[] = $productId;
        $product    = Mage::getModel('catalog/product')->setStoreId($order->getStoreId())->load($productId);
        $data       = $product->getStockData(); 

        $discount   = $data['qty'] < 1 ? true : false;

        if ($product->getAutoDiscountAllowed())
        { 
            $product->setAutoDiscountActive($discount);
            $product->save();
        }

        Mage::getModel('catalogrule/rule')->applyAllRulesToProduct($productId);
    }
    return $this;
}

在下订单并在后台手动保存购买的商品后,价格规则会更新。但是我已经在我的观察者方法中进行了更新。

更改自定义属性后,我需要做什么才能分配目录价格规则?

提前致谢!

最佳答案

好的,我想就一些相当重要的代码优化向您提出建议。

您可以减少集合大小并删除循环内的条件逻辑,方法是:

$order->getItemsCollection()->addFieldToFilter('is_in_stock', 0);

您还可以使用比 save() 更快的方法更新所有属性,方法是:

Mage::getSingleton('catalog/product_action')
    ->updateAttributes($order->getItemsCollection()->addFieldToFilter('is_in_stock', 0)->getAllIds(), array('auto_discount_active' => 1), 0);

此外,请记住,您还需要将您的观察员应用于任何产品库存水平的修改,即。产品保存、导入、贷项通知单(退款)——因此它是一个相当广阔的领域。重写 stock 类可能会更好,因为没有太多事件派发给你足够的范围来涵盖这个。

最后,为了执行规则分配,我建议扩展规则的资源模型 (Mage/CatalogRule/Model/Mysql4/Rule.php) 以便您可以传入数组产品 ID(以保存它遍历整个目录)。

您可以简单地扩展 getRuleProductIds() 以获取一个 Mage::registry 变量(如果已设置)以及您从上述集合中获取的产品 ID。然后在运行上面的代码后,你可以执行

Mage::getModel('catalogrule/rule')->load(myruleid)->save();

这将根据需要重新编制索引并将规则应用于新产品 - 仅适用于已更改的产品。

我认为这种方法可以极大地减少管理费用。

关于php - Magento - 修改产品属性后重新分配目录规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7387901/

有关php - Magento - 修改产品属性后重新分配目录规则的更多相关文章

  1. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  2. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  3. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  4. Ruby Koans about_array_assignment - 非平行与平行分配歧视 - 2

    通过ruby​​koans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John

  5. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  6. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  7. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  8. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  9. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

  10. ruby-on-rails - 如何在 Gem 中获取 Rails 应用程序的根目录 - 2

    是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在

随机推荐