จะ“ เพิ่มสินค้าลงตะกร้า” ผลิตภัณฑ์ที่มีฟิลด์ป้อนข้อมูลที่กำหนดเองและบันทึกลงในฐานข้อมูลได้อย่างไร


9

ฉันได้สร้างโมดูลที่กำหนดเองที่ฉันจะเอาชนะแบบฟอร์มการเพิ่มลงในรถเข็นในหน้าผลิตภัณฑ์และฉันก็ทำมันสำเร็จด้วยcatalog_product_view.xmlไฟล์ ตอนนี้ฉันสามารถเห็นฟิลด์อินพุตที่กำหนดเองในมุมมองด้านหน้าของหน้าผลิตภัณฑ์ แต่ฉันต้องโพสต์ค่าของฟิลด์นี้ไปยังฐานข้อมูลด้วยจำนวนราคาและอื่น ๆ และเรียกมันอีกครั้งในประวัติการสั่งซื้อ

ฉันค้นหามาระยะหนึ่งแล้วก็ประสบความสำเร็จในการสร้างคอลัมน์ที่กำหนดเองใหม่ในquote_item& sales_orderตาราง (ตามข้อมูลของฉันเพิ่มไปที่รถเข็นรายการไปที่quote_itemและคำสั่งซื้อหลังจากเช็คเอาต์ไปที่sales_orderตารางหากฉันผิดโปรดแก้ไขฉันด้วยเช่นกันเนื่องจากฉันยังเป็นผู้เรียนอยู่)

ฉันพยายามมากและค้นหา แต่ไม่พบโซลูชันที่เกี่ยวข้อง ผู้ขายชื่อของฉันคือCloudwaysและชื่อโมดูลMyModule ด้านล่างนี้เป็นไฟล์สำหรับโมดูลของฉัน:

Cloudways / MyModule / registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Cloudways_Mymodule',
    __DIR__
);

Cloudways / MyModule / etc / module.xml

<?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Cloudways_Mymodule" setup_version="1.0.1"></module>
</config>

Cloudways / MyModule / ติดตั้ง / UpgradeSchema.php

<?php

namespace Cloudways\Mymodule\Setup;

use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;

class UpgradeSchema implements UpgradeSchemaInterface
{
    public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        if (version_compare($context->getVersion(), '1.0.1') < 0) {

        $installer = $setup;
        $installer->startSetup();
        $connection = $installer->getConnection();
        //cart table
        $connection->addColumn(
                $installer->getTable('quote_item'),
                'remarks',
                [
                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                    'length' => 255,
                    'comment' =>'Remarks'
                ]
            );
        //Order address table
        $connection->addColumn(
                $installer->getTable('sales_order'),
                'remarks',
                [
                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                    'length' => 255,
                    'comment' =>'Remarks'

                ]
            );
        $installer->endSetup(); }
    }
}

Cloudways / MyModule / ดู / ส่วนหน้า / รูปแบบ / catalog_product_view.xml

<?xml version="1.0"?>
<page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="product.info.addtocart">
            <action method="setTemplate">
                <argument name="template" xsi:type="string">Cloudways_Mymodule::catalog/product/view/addtocart.phtml</argument>
            </action>
        </referenceBlock>
        <referenceBlock name="product.info.addtocart.additional">
            <action method="setTemplate">
                <argument name="template" xsi:type="string">Cloudways_Mymodule::catalog/product/view/addtocart.phtml</argument>
            </action>
        </referenceBlock>
    </body>
</page>

Cloudways / MyModule / view / ส่วนหน้า / แม่ / แคตตาล็อกสินค้า / / view / addtocart.phtml

<?php
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

// @codingStandardsIgnoreFile

/** @var $block \Magento\Catalog\Block\Product\View */
?>
<?php $_product = $block->getProduct(); ?>
<?php $buttonTitle = __('Add to Cart'); ?>
<?php if ($_product->isSaleable()): ?>
<div class="box-tocart">
    <div class="fieldset">
        <?php if ($block->shouldRenderQuantity()): ?>
        <div class="field qty">
            <label class="label" for="qty"><span><?php /* @escapeNotVerified */ echo __('Qty') ?></span></label>
            <div class="control">
                <input type="number"
                       name="qty"
                       id="qty"
                       maxlength="12"
                       value="<?php /* @escapeNotVerified */ echo $block->getProductDefaultQty() * 1 ?>"
                       title="<?php /* @escapeNotVerified */ echo __('Qty') ?>" class="input-text qty"
                       data-validate="<?php echo $block->escapeHtml(json_encode($block->getQuantityValidators())) ?>"
                       />
            </div>
        </div>
        <!-- Custom Input Field -->
        <div>
            <input
                type="text"
                name="remarks"
                id="remarks"
                maxlength="255"
                placeholder="Remarks"
            />
        </div>
        <!-- Custom Input Field -->
        <br>
        <?php endif; ?>
        <div class="actions">
            <button type="submit"
                    title="<?php /* @escapeNotVerified */ echo $buttonTitle ?>"
                    class="action primary tocart"
                    id="product-addtocart-button">
                <span><?php /* @escapeNotVerified */ echo $buttonTitle ?></span>
            </button>
            <?php echo $block->getChildHtml('', true) ?>
        </div>
    </div>
</div>
<?php endif; ?>
<?php if ($block->isRedirectToCartEnabled()) : ?>
<script type="text/x-magento-init">
    {
        "#product_addtocart_form": {
            "Magento_Catalog/product/view/validation": {
                "radioCheckboxClosest": ".nested"
            }
        }
    }
</script>
<?php else : ?>
<script>
    require([
        'jquery',
        'mage/mage',
        'Magento_Catalog/product/view/validation',
        'Magento_Catalog/js/catalog-add-to-cart'
    ], function ($) {
        'use strict';

        $('#product_addtocart_form').mage('validation', {
            radioCheckboxClosest: '.nested',
            submitHandler: function (form) {
                var widget = $(form).catalogAddToCart({
                    bindSubmit: false
                });

                widget.catalogAddToCart('submitForm', $(form));

                return false;
            }
        });
    });
</script>
<?php endif; ?>

นี่คือภาพหน้าจอของมุมมองด้านหน้า:

ป้อนคำอธิบายรูปภาพที่นี่

ทั้งหมดที่ฉันต้องการคือการโพสต์ค่าของฟิลด์อินพุตที่กำหนดเองและบันทึกไว้ในฐานข้อมูลพร้อมกับการสั่งซื้อ ขอบคุณล่วงหน้า!

แก้ไข: ฉันทำการเปลี่ยนแปลงที่เคารพตามคำตอบของ RS และนี่คือปัญหาที่ฉันเผชิญ: (PS I AM ใช้ MAGENTO 2.0.9)

ป้อนคำอธิบายรูปภาพที่นี่

ฉันตรวจสอบล็อกไฟล์แล้วและนี่คือสิ่งที่ฉันพบ:

[2016-08-26 07:29:38] main.CRITICAL: exception 'Exception' with message 'Report ID: webapi-57bfefe2d8272; Message: Warning: Invalid argument supplied for foreach() in /home/41209-54048.cloudwaysapps.com/yyzmyegjdk/public_html/app/code/Cloudways/Mymodule/Observer/SalesModelServiceQuoteSubmitBeforeObserver.php on line 67' in /home/41209-54048.cloudwaysapps.com/yyzmyegjdk/public_html/vendor/magento/framework/Webapi/ErrorProcessor.php:194
Stack trace:
#0 /home/41209-54048.cloudwaysapps.com/yyzmyegjdk/public_html/vendor/magento/framework/Webapi/ErrorProcessor.php(139): Magento\Framework\Webapi\ErrorProcessor->_critical(Object(Exception))
#1 /home/41209-54048.cloudwaysapps.com/yyzmyegjdk/public_html/vendor/magento/module-webapi/Controller/Rest.php(163): Magento\Framework\Webapi\ErrorProcessor->maskException(Object(Exception))
#2 /home/41209-54048.cloudwaysapps.com/yyzmyegjdk/public_html/var/generation/Magento/Webapi/Controller/Rest/Interceptor.php(24): Magento\Webapi\Controller\Rest->dispatch(Object(Magento\Framework\App\Request\Http))
#3 /home/41209-54048.cloudwaysapps.com/yyzmyegjdk/public_html/vendor/magento/framework/App/Http.php(115): Magento\Webapi\Controller\Rest\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#4 /home/41209-54048.cloudwaysapps.com/yyzmyegjdk/public_html/vendor/magento/framework/App/Bootstrap.php(258): Magento\Framework\App\Http->launch()
#5 /home/41209-54048.cloudwaysapps.com/yyzmyegjdk/public_html/index.php(39): Magento\Framework\App\Bootstrap->run(Object(Magento\Framework\App\Http))
#6 {main} [] []

ข้อเสนอแนะใด ๆ โปรด?


ลองดูที่นี่วีโอไอพี 1 ตัวอย่างเช่นstackoverflow.com/questions/9412074/... ... คุณควรจะสามารถที่จะใช้ "additional_options" ในการจัดเก็บข้อมูลนี้โดยใช้ผู้สังเกตการณ์github.com/magento/magento2/... ... การใช้ additional_options จะแสดงข้อมูลนี้โดยอัตโนมัติในผู้ดูแลระบบอีเมลใบสั่งขาย ฯลฯ
Renon Stewart

มีเหตุผลที่คุณไม่ได้ใช้ผลิตภัณฑ์ง่าย ๆ พร้อมตัวเลือกที่กำหนดเองเพื่อทำสิ่งนี้ให้สำเร็จหรือไม่?
Renon Stewart

@RS ฉันต้องทำโดยทางโปรแกรมเพราะเราจะขยายรถเข็นที่กำหนดเองนี้ด้วยตัวเลือกที่แตกต่างกันซึ่งฉันคิดว่าสามารถทำได้กับโมดูลที่กำหนดเองเท่านั้น
Fayyaz Khattak

คุณสามารถเพิ่มลิงก์ (github) ลงในรหัสของคุณได้ไหมดังนั้นฉันสามารถดาวน์โหลดและลองใช้เพิ่มเติม
_options

@RS ใช่แน่นอนโปรดให้ฉันสองสามนาที
Fayyaz Khattak

คำตอบ:


14

เพื่อให้บรรลุนี้คุณสามารถใช้ magento builtin ในฟังก์ชั่น "เพิ่มเติม _options" เพื่อให้คุณไม่ต้องแก้ไขเทมเพลตอีเมล, มุมมองคำสั่งซื้อของผู้ดูแลระบบ, มุมมองคำสั่งซื้อของลูกค้า (ฯลฯ ) เพื่อแสดงตัวเลือกที่กำหนดเองของคุณ

Github: https://github.com/srenon/Cloudways_Mymodule

/app/code/Cloudways/Mymodule/etc/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="checkout_cart_product_add_after">
        <observer name="cloudways_mymodule_checkout_cart_product_add_after" instance="Cloudways\Mymodule\Observer\CheckoutCartProductAddAfterObserver" />
    </event>
    <event name="sales_model_service_quote_submit_before">
        <observer name="cloudways_mymodule_sales_model_service_quote_submit_before" instance="Cloudways\Mymodule\Observer\SalesModelServiceQuoteSubmitBeforeObserver" />
    </event>
</config>

เพิ่มตัวเลือกในการอ้างอิง

/app/code/Cloudways/Mymodule/Observer/CheckoutCartProductAddAfterObserver.php

<?php

namespace Cloudways\Mymodule\Observer;

use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\RequestInterface;

class CheckoutCartProductAddAfterObserver implements ObserverInterface
{

    protected $_request;

    /**
     * @param RequestInterface $request
     */
    public function __construct(RequestInterface $request){
            $this->_request = $request;
    }

    /**
     * @param EventObserver $observer
     * @return void
     */
    public function execute(EventObserver $observer)
    {
        /* @var \Magento\Quote\Model\Quote\Item $item */
        $item = $observer->getQuoteItem();

        $additionalOptions = array();

        if ($additionalOption = $item->getOptionByCode('additional_options')){
            $additionalOptions = (array) unserialize($additionalOption->getValue());
        }

        $post = $this->_request->getParam('cloudways');

        if(is_array($post)){
            foreach($post as $key => $value){
                if($key == '' || $value == ''){
                    continue;
                }

                $additionalOptions[] = [
                    'label' => $key,
                    'value' => $value
                ];
            }
        }

        if(count($additionalOptions) > 0){
            $item->addOption(array(
                'code' => 'additional_options',
                'value' => serialize($additionalOptions)
            ));
        }


        /* To Do */

        // Edit Cart - May need to remove option and readd them
        // Pre-fill remarks on product edit pages


        /* Issues */

        // Create new cart item with identical option values will add a new line item, instead of increment previous item qty

    }
}

วิธีที่ # 1 - การคัดลอกตัวเลือกจาก quote_item ถึง order_item โดยใช้ ObserverดูMagento 2 fieldset.xml; คัดลอกฟิลด์จากคำพูดไปยังการสั่งซื้อ

/app/code/Cloudways/Mymodule/Observer/SalesModelServiceQuoteSubmitBeforeObserver.php

<?php

namespace Cloudways\Mymodule\Observer;

use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;


class SalesModelServiceQuoteSubmitBeforeObserver implements ObserverInterface
{

    private $quoteItems = [];

    private $quote = null;
    private $order = null;

    /**
     * Add order information into GA block to render on checkout success pages
     *
     * @param EventObserver $observer
     * @return void
     */
    public function execute(EventObserver $observer)
    {

        $this->quote = $observer->getQuote();
        $this->order = $observer->getOrder();

        // can not find an equivalent event for sales_convert_quote_item_to_order_item


        /* @var  \Magento\Sales\Model\Order\Item $orderItem */
        foreach($this->order->getItems() as $orderItem){
            if(!$orderItem->getParentItemId() && $orderItem->getProductType() == \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE){

                if($quoteItem = $this->getQuoteItemById($orderItem->getQuoteItemId())){
                    if ($additionalOptionsQuote = $quoteItem->getOptionByCode('additional_options')) {

                        //To do
                        // - check to make sure element are not added twice
                        // - $additionalOptionsQuote - may not be an array
                        if($additionalOptionsOrder = $orderItem->getProductOptionByCode('additional_options')){
                            $additionalOptions = array_merge($additionalOptionsQuote, $additionalOptionsOrder);
                        }
                        else{
                            $additionalOptions = $additionalOptionsQuote;
                        }


                        if(count($additionalOptions) > 0){
                            $options = $orderItem->getProductOptions();
                            $options['additional_options'] = unserialize($additionalOptions->getValue());
                            $orderItem->setProductOptions($options);
                        }

                    }
                }
            }
        }

    }


    private function getQuoteItemById($id){
        if(empty($this->quoteItems)){
            /* @var  \Magento\Quote\Model\Quote\Item $item */
            foreach($this->quote->getItems() as $item){

                //filter out config/bundle etc product
                if(!$item->getParentItemId() && $item->getProductType() == \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE){
                    $this->quoteItems[$item->getId()] = $item;
                }
            }
        }


        if(array_key_exists($id, $this->quoteItems)){
            return $this->quoteItems[$id];
        }

        return null;
    }
}

วิธี # 2 - คัดลอกตัวเลือกจาก quote_item เพื่อ order_item โดยใช้ปลั๊กอิน

/app/code/Cloudways/Mymodule/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Quote\Model\Quote\Item\ToOrderItem">
        <plugin name="cloudways_mymodule\_Sales_Quote_Item_ToOrderItem" type="Cloudways\Mymodule\Plugin\QuoteItemToOrderItemPlugin" />
    </type>
</config>

/app/code/Cloudways/Mymodule/Plugin/QuoteItemToOrderItemPlugin.php

<?php

namespace Cloudways\Mymodule\Plugin;

class QuoteItemToOrderItemPlugin
{

    public function aroundConvert(\Magento\Quote\Model\Quote\Item\ToOrderItem $subject, callable $proceed, $quoteItem, $data)
    {

        // get order item
        $orderItem = $proceed($quoteItem, $data);


        if(!$orderItem->getParentItemId() && $orderItem->getProductType() == \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE){
            if ($additionalOptionsQuote = $quoteItem->getOptionByCode('additional_options')) {
                //To do
                // - check to make sure element are not added twice
                // - $additionalOptionsQuote - may not be an array
                if($additionalOptionsOrder = $orderItem->getProductOptionByCode('additional_options')){
                    $additionalOptions = array_merge($additionalOptionsQuote, $additionalOptionsOrder);
                }
                else{
                    $additionalOptions = $additionalOptionsQuote;
                }
                if(count($additionalOptions) > 0){
                    $options = $orderItem->getProductOptions();
                    $options['additional_options'] = unserialize($additionalOptions->getValue());
                    $orderItem->setProductOptions($options);
                }
            }
        }

        return $orderItem;
    }
}

ตะกร้าสินค้าและหน้าดูคำสั่งซื้อของผู้ดูแลระบบ

ฐานของMagento1 - อ้าง / สั่งซื้อแอตทริบิวต์รายการสินค้าตามการป้อนข้อมูลของผู้ใช้


@renon ฉันลองใช้ฟังก์ชันการทำงานข้างต้นสำหรับผลิตภัณฑ์ที่เรียบง่ายและใช้งานได้ดีขอบคุณ! แต่ฉันต้องการเหมือนกันสำหรับผลิตภัณฑ์ที่กำหนดค่าได้แต่ฉันได้รับข้อผิดพลาดในหน้าตะกร้าสินค้า "ตัวเลือกที่เลือกไว้หรือชุดค่าผสมไม่พร้อมใช้งานในขณะนี้" ฉันรู้ว่าทำไมปัญหานี้เกิดขึ้น แต่มีวิธีใดที่จะเอาชนะได้ฉันหมายถึงกรองตัวเลือกเฉพาะออกหรือไม่
Nausif

เพียงแค่ใช้มันและมันก็ทำงานได้เหมือนมีเสน่ห์ ขอบคุณ! คุณทราบถึงฟังก์ชั่นใด ๆ ใน Magento ที่อนุญาตให้ใช้คุณสมบัติต่อรายการ (ไม่ใช่ต่อผลิตภัณฑ์) ตัวอย่างเช่นข้อความที่กำหนดเองบนเสื้อ แต่ในขณะที่มีหลายเสื้อเดียวกันกับข้อความที่แตกต่างกัน Magento ตอนนี้รวมผลิตภัณฑ์เหล่านั้นไว้ในรถเข็นและทำให้ฉันสูญเสียการตั้งค่าเฉพาะต่อรายการ
Jurgen

@ Nausif ฉันประสบปัญหาเดียวกัน แต่ตอนนี้มันได้รับการแก้ไข อ้างถึง url นี้ - magento.stackexchange.com/questions/177133/ …
Kishor Hase

@renon ฉันใช้สิ่งนี้และค่าต่างๆแสดงใน mini-cart, cart และ checkout ฉันมีผลิตภัณฑ์ที่กำหนดค่าได้เพื่อทำสิ่งนี้ ฉันลองทั้งสองวิธีการแปลงใบเสนอราคา แต่ค่าไม่แสดงในส่วนคำสั่งซื้อจดหมายและใบสั่งในผู้ดูแลระบบ
Rishabh Rk Rai

ถ้าใคร[invalidargumentexception] unable to unserialize value.ใช้ json_encode และ json_decode แทน serialize และ unserialize
Ebin Manuval

0

ในการแก้ไขปัญหานี้: // สร้างรายการรถเข็นใหม่ที่มีค่าตัวเลือกเหมือนกันจะเพิ่มรายการโฆษณาใหม่แทนที่จะเพิ่มจำนวนรายการก่อนหน้า

ฉันได้เพิ่มหลังจากปลั๊กอินสำหรับวิธีแสดงผลิตภัณฑ์ใน Magento \ Quote \ Model \ Quote \ Item ในปลั๊กอินฉันตรวจสอบว่ามันเป็นพารามิเตอร์ที่จำเป็นเพิ่มเติมของฉันและถ้ามันเป็นผลตอบแทนที่ต้องการ (จริง)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.