사용자 정의 입력 필드가있는 제품을 "장바구니에 추가"하고 데이터베이스에 저장하는 방법은 무엇입니까?


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 / Setup / 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 / view / frontend / layout / 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 / frontend / templates / catalog / product / 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는 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} [] []

제발 어떤 제안?


이 magento 1 예제 stackoverflow.com/questions/9412074 / ...를보십시오. ... "additional_options"를 사용하여 관찰자 github.com/magento/magento2 / ...를 사용 하여이 정보를 저장할 수 있어야합니다 . ... ... additional_options 사용 이 정보를 관리자, 판매 주문 이메일 등에 자동으로 표시합니다
Renon Stewart

이를 수행하기 위해 사용자 정의 옵션이있는 단순 제품을 사용하지 않는 이유가 있습니까?
Renon Stewart

@RS 나는 사용자 정의 모듈로만 수행 할 수 있다고 생각되는 다른 사용자 정의 옵션 으로이 사용자 정의 카트를 추가로 확장하기 때문에 프로그래밍 방식으로해야합니다.
Fayyaz Khattak

코드에 (github) 링크를 추가 할 수 있으므로 additional_options를 다운로드하여 구현할 수 있습니다.
Renon Stewart

@RS 예, 몇 분만주세요.
Fayyaz Khattak

답변:


14

이를 위해 magento 내장 "additional_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으로 옵션 복사하기 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 나는 이것을 사용하고 값은 미니 카트, 카트 및 체크 아웃으로 표시됩니다. 이를 위해 구성 가능한 제품이 있습니다. 견적 변환 방법을 모두 시도했지만 관리자의 주문 메일 및 주문 섹션에 값이 표시되지 않습니다.
Rishabh Rk Rai

사람이 얻는 경우 [invalidargumentexception] unable to unserialize value.사용로 json_encode 대신 직렬화하고 때 unserialize의 json_decode
EBIN Manuval을

0

이 문제를 해결하려면 // 동일한 옵션 값으로 새 장바구니 항목을 만들면 이전 항목 수량을 늘리는 대신 새 광고 항목이 추가됩니다.

Magento \ Quote \ Model \ Quote \ Item에 method represent 메소드에 대한 플러그인 다음에 추가했습니다. 플러그인에서 필요한 추가 매개 변수인지 확인하고 필요한 결과가 반환되는지 확인하십시오 (true).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.