php Magento - 根据用户输入报价/订购产品项目属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9412074/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 06:45:26  来源:igfitidea点击:

Magento - Quote/order product item attribute based on user input

phpmagento

提问by Vitamin

Summary

概括

I want to create a product attribute that is not saved to products, or displayed on the product edit page like ordinary product attributes. Instead I want it to be saved to order/quote items and displayed on orders, invoices and such. It should also be configurable by the customer in the frontend before adding a product to the cart.

我想创建一个不保存到产品中的产品属性,或者像普通产品属性一样显示在产品编辑页面上。相反,我希望将其保存到订单/报价项目并显示在订单、发票等上。在将产品添加到购物车之前,它也应该由客户在前端进行配置。

Details

细节

  • Just like with Custom Options, a form element should be added to the frontend product page.
    • UnlikeCustom Options, this is not an actualproduct attribute. It should not be displayed on the admin product pages or attribute sets.
    • The customer is required to provide a valid value. I need to be able to do server-side validation.
    • I want to have a .phtml template generating its html. Currently I'm able to override app/design/frontend/base/default/catalog/product/view/type/default.phtmlwith satisfactory (design) results. However I don't know how to capture, validate and eventually save its value.
  • The value of this form element should be saved with the quote/order product item.
    • This value should be displayed on any and all invoices, orders, sales emails.
    • I want to control output with a template, or at least be able to return the string that is used to display the value
  • 就像自定义选项一样,应将表单元素添加到前端产品页面。
    • 自定义选项不同,这不是实际的产品属性。它不应显示在管理产品页面或属性集上。
    • 客户需要提供有效值。我需要能够进行服务器端验证。
    • 我想要一个 .phtml 模板生成它的 html。目前,我能够以令人满意的(设计)结果覆盖app/design/frontend/base/default/catalog/product/view/type/default.phtml。但是我不知道如何捕获、验证并最终保存它的价值。
  • 此表单元素的值应与报价/订单产品项目一起保存。
    • 该值应显示在任何和所有发票、订单、销售电子邮件中。
    • 我想用模板控制输出,或者至少能够返回用于显示值的字符串

My questions

我的问题

  1. How do I validate and eventually save the value from a <input>on the frontend product page to the quote item when the product is added to the cart, and later in the checkout process to the order item?
  2. How do I display this value on the order, invoice, sales emails and such pages?
  3. How do I filter an order collection to fetch orders that has items with my value set to a specific value?
  1. <input>当产品被添加到购物车时,我如何验证并最终将前端产品页面上的值保存到报价项目,然后在结账过程中保存到订单项目?
  2. 如何在订单、发票、销售电子邮件和此类页面上显示此值?
  3. 如何过滤订单集合以获取将我的值设置为特定值的项目的订单?

Update 1

更新 1

I've discovered that I can run this code on a catalog/productmodel (and probably sales/quote_itemas well) during events such as sales_quote_item_qty_set_after

我发现我可以在catalog/product模型上运行此代码(可能也sales/quote_item一样)在诸如sales_quote_item_qty_set_after

$infoBuyRequest = $product->getCustomOption('info_buyRequest');
$buyRequest = new Varien_Object(unserialize($infoBuyRequest->getValue()));
$myData = $buyRequest->getMyData();

In this way I was able to retrieve my custom, customer supplied, data from my <input>on the product page.

通过这种方式,我能够从我<input>的产品页面上检索我的自定义、客户提供的数据。

I suspect this info_buyRequestis saved with the quote and order items. If so, this partiallysolved my problems 1 and 2. However, I still dont know where it's suitable to run this code, and I dont know how to display it on the backend order/quote/report pages. Also I belive since this is stored as a serialized value in the database, it will be most difficult to get quote/order item collections based on my custom data.

我怀疑这info_buyRequest与报价和订单项目一起保存。如果是这样,这部分解决了我的问题 1 和 2。但是,我仍然不知道在哪里运行这段代码是合适的,我也不知道如何在后端订单/报价/报告页面上显示它。我也相信,因为它是作为序列化值存储在数据库中的,所以根据我的自定义数据获取报价/订单项目集合将是最困难的。

回答by Vinai

Magento provides a capability for adding options that aren't product attributes or product custom options. They are set on the product and quote items with the option code additional_options.

Magento 提供了添加不是产品属性或产品自定义选项的选项的功能。它们设置在带有选项代码的产品和报价项目上additional_options

There are two steps you need to take, each can be handled via an event observer. If you want the additional options to carry through reordering, you will need also observe a third event.

您需要执行两个步骤,每个步骤都可以通过事件观察器进行处理。如果您希望其他选项通过重新排序进行,您还需要观察第三个事件。

Add options to quote item

添加选项以引用项目

The first step is to add the event observer to set the additional options on the loaded product before it is added to the cart. One option is to use the catalog_product_load_afterevent.

第一步是添加事件观察器,以便在加载的产品添加到购物车之前为其设置附加选项。一种选择是使用catalog_product_load_after事件。

<catalog_product_load_after>
    <observers>
        <extra_options>
            <type>model</type>
            <class>extra_options/observer</class>
            <method>catalogProductLoadAfter</method>
        </extra_options>
    </observers>
</catalog_product_load_after>

In the event observer you can add additional checks the requested page is indeed an add to cart action. The main point of this observer method is to add the selection of your special options to the additional_optionsoption on the product model.

在事件观察者中,您可以添加额外的检查请求的页面确实是添加到购物车的操作。这种观察者方法的要点是将您的特殊选项的选择添加到additional_options产品模型上的选项中。

public function catalogProductLoadAfter(Varien_Event_Observer $observer)
{
    // set the additional options on the product
    $action = Mage::app()->getFrontController()->getAction();
    if ($action->getFullActionName() == 'checkout_cart_add')
    {
        // assuming you are posting your custom form values in an array called extra_options...
        if ($options = $action->getRequest()->getParam('extra_options'))
        {
            $product = $observer->getProduct();

            // add to the additional options array
            $additionalOptions = array();
            if ($additionalOption = $product->getCustomOption('additional_options'))
            {
                $additionalOptions = (array) unserialize($additionalOption->getValue());
            }
            foreach ($options as $key => $value)
            {
                $additionalOptions[] = array(
                    'label' => $key,
                    'value' => $value,
                );
            }
            // add the additional options array with the option code additional_options
            $observer->getProduct()
                ->addCustomOption('additional_options', serialize($additionalOptions));
        }
    }
}

The additional options will be moved from the product to the quote item automatically. With this observer in place, your options will appear in the cart and the checkout review.

附加选项将自动从产品移动到报价项目。有了这个观察者,您的选项将出现在购物车和结帐评论中。

Add options to order item

添加选项以订购商品

In order to have them persist, one additional observer is needed (only since Magento 1.5).

为了让它们持久化,需要一个额外的观察者(仅自 Magento 1.5 起)。

<sales_convert_quote_item_to_order_item>
    <observers>
        <extra_options>
            <type>model</type>
            <class>extra_options/observer</class>
            <method>salesConvertQuoteItemToOrderItem</method>
        </extra_options>
    </observers>
</sales_convert_quote_item_to_order_item>

Here we move the option from the quote item to the order item.

在这里,我们将选项从报价项目移动到订单项目。

public function salesConvertQuoteItemToOrderItem(Varien_Event_Observer $observer)
{
    $quoteItem = $observer->getItem();
    if ($additionalOptions = $quoteItem->getOptionByCode('additional_options')) {
        $orderItem = $observer->getOrderItem();
        $options = $orderItem->getProductOptions();
        $options['additional_options'] = unserialize($additionalOptions->getValue());
        $orderItem->setProductOptions($options);
    }
}

From this point on the additional options will be visible in the customer order history in the frontend and the order emails, as well as in the admin interface order view, invoices, shipments, creditmemos and PDFs.

从这一点开始,附加选项将在前端的客户订单历史记录和订单电子邮件以及管理界面订单视图、发票、发货、贷项凭证和 PDF 中可见。

Add support for reorders

添加对重新排序的支持

In order to carry the oprions over to the new order during a reorder, you need to take care to copy them over. Here is one possibility using the checkout_cart_product_add_afterevent.

为了在重新订购期间将 oprions 转移到新订单,您需要小心地复制它们。这是使用checkout_cart_product_add_after事件的一种可能性。

<checkout_cart_product_add_after>
    <observers>
        <extra_options>
            <type>singleton</type>
            <class>extra_options/observer</class>
            <method>checkoutCartProductAddAfter</method>
        </extra_options>
    </observers>
</checkout_cart_product_add_after>

The parsing of the extra options and building the additional options array should be moved into a separate function to avoid code duplication, but for this example I'll leave the required logic for each method in place for clarity.

额外选项的解析和构建额外的选项数组应该移到一个单独的函数中以避免代码重复,但在这个例子中,为了清楚起见,我将保留每个方法所需的逻辑。

public function checkoutCartProductAddAfter(Varien_Event_Observer $observer)
{
    $action = Mage::app()->getFrontController()->getAction();
    if ($action->getFullActionName() == 'sales_order_reorder')
    {
        $item = $observer->getQuoteItem();
        $buyInfo = $item->getBuyRequest();
        if ($options = $buyInfo->getExtraOptions())
        {
            $additionalOptions = array();
            if ($additionalOption = $item->getOptionByCode('additional_options'))
            {
                $additionalOptions = (array) unserialize($additionalOption->getValue());
            }
            foreach ($options as $key => $value)
            {
                $additionalOptions[] = array(
                    'label' => $key,
                    'value' => $value,
                );
            }
            $item->addOption(array(
                'code' => 'additional_options',
                'value' => serialize($additionalOptions)
            ));
        }
    }
}

Translation:

翻译:

There is no mechanism in place to translate these option labels or values. Here are a few ideas that might be useful in that regard.

没有适当的机制来转换这些选项标签或值。以下是一些可能在这方面有用的想法。

In a quote_item_load_after event observer, get the additional options array and set $option['print_value'] = $helper->__($option['value']);. If print_valueis set, Magento will use that for rendering the display.
The same can be done with order items.

在 quote_item_load_after 事件观察者中,获取附加选项数组并设置$option['print_value'] = $helper->__($option['value']);。如果print_value设置,Magento 将使用它来渲染显示。
订单项也可以这样做。

There is no such thing as a print_label, but you could set a custom index (label_sourcemaybe) and set the label on the fly using that as the source, e.g. $option['label'] = $helper->__($option['label_source']);.

没有像 a 这样的东西print_label,但是您可以设置自定义索引(label_source也许)并使用它作为源动态设置标签,例如$option['label'] = $helper->__($option['label_source']);.

Beyond that you would probably have to resort to modifying the templates (grep for getItemOptions()), or overriding the block classes (grep additional_options).

除此之外,您可能不得不求助于修改模板(grep for getItemOptions()),或覆盖块类(grep additional_options)。

回答by Jim OHalloran

It is possible to add custom fields to the Quote item. How to add custom fields for Order Line Itemsin Magento to get started. I've used these instruction recently to add a custom fields to a Magento Quote Item and the concept is fine, but there are a few practices in that article that are not great. Things I'd do differently:

可以向报价项添加自定义字段。 如何在 Magento 中为订单行项目添加自定义字段以开始使用。我最近使用这些指令将自定义字段添加到 Magento Quote Item 中,这个概念很好,但那篇文章中有一些不太好的做法。我会做不同的事情:

  1. Use a setup script to add fields to the database rather than doing it directly.
  2. Use Magento's Request object rather than accessing $_REQUEST directly.
  3. Use extensions and rewrites rather than modifying the Magento core.
  4. Make the changes to config.xml from an extension rather than modifying the core.
  1. 使用设置脚本向数据库添加字段而不是直接添加字段。
  2. 使用 Magento 的 Request 对象而不是直接访问 $_REQUEST 。
  3. 使用扩展和重写而不是修改 Magento 核心。
  4. 从扩展中更改 config.xml 而不是修改核心。

Generally it's best to avoid modifying the Magento core, and apply your customisations via a module as it makes upgrades easier/possible in the future. If you've not created your own extension before moduleCreatorcan help you generate the necessary boilerplate.

通常最好避免修改 Magento 核心,并通过模块应用您的自定义,因为它使将来的升级更容易/可能。如果在moduleCreator可以帮助您生成必要的样板之前,您还没有创建自己的扩展。

回答by wutzebaer

My Solution in Magento 1.8

我在 Magento 1.8 中的解决方案

Set option to quote item

设置选项以引用项目

$quoteItem = $cart->getQuote()->getItemById($itemId);
$quoteItem->addOption(array('label' => 'buymode', 'code' => 'buymode', 'value' => $data['buymode']));
$quoteItem->save();

Access option from QuoteItem

从 QuoteItem 访问选项

$quoteItem->getOptionByCode('buymode')->getValue();

Transfer option to OrderItem

将选项转移到 OrderItem

Register for event sales_convert_quote_item_to_order_item

注册活动 sales_convert_quote_item_to_order_item

public function onConvertQuoteItemToOrderItem($observer) {
    $orderItem = $observer->getOrderItem();
    $quoteItem = $observer->getItem();
    $options = $orderItem->getProductOptions();
    $options['buymode'] = $quoteItem->getOptionByCode('buymode')->getValue();
    $orderItem->setProductOptions($options);
}

Access option from OrderItem

来自 OrderItem 的访问选项

$orderItem->getProductOptionByCode('buymode')