dongyou6847 2012-02-23 11:23
浏览 37
已采纳

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

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.
    • Unlike Custom Options, this is not an actual product 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.phtml with 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

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?

Update 1

I've discovered that I can run this code on a catalog/product model (and probably sales/quote_item as well) during events such as 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.

I suspect this info_buyRequest is saved with the quote and order items. If so, this partially solved 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.

  • 写回答

3条回答 默认 最新

  • duanhangjian8149 2012-02-29 09:10
    关注

    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.

    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_after event.

    <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_options option on the product model.

    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).

    <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.

    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_after event.

    <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_value is set, Magento will use that for rendering the display.
    The same can be done with order items.

    There is no such thing as a print_label, but you could set a custom index (label_source maybe) and set the label on the fly using that as the source, e.g. $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).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿
  • ¥15 回答4f系统的像差计算
  • ¥15 java如何提取出pdf里的文字?