Як "додати в кошик" продукт із спеціальним полем для введення та зберегти його в базі даних?


9

Я створив спеціальний модуль, в якому я переосмислював форму додавання в кошик на сторінці продукту, і я успішно це зробив з catalog_product_view.xmlфайлом. Тепер я бачу на власному полі введення на сторінці спереду сторінки продукту, але мені потрібно розмістити значення цього поля в базі даних з Qty, ціною тощо та знову отримати його в історії замовлень.

Я деякий час шукав, а також отримав успіх у створенні нових спеціальних стовпців у 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 / тощо / 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 / шаблони / каталог / продукт / 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; ?>

Ось знімок виду спереду:

введіть тут опис зображення

Все, що мені потрібно - це розмістити значення спеціального поля введення та зберегти його в базі даних разом із замовленням. Спасибі заздалегідь!

РЕДАКТИРУЙТЕ: Я Зробив респективні зміни відповідно до відповіді РС, і тут є проблема, яку я знаходжу: (PS Я ВИКОРИСТОВУЮ 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

Чи є причина, що ви не використовуєте для цього простого продукту зі спеціальними параметрами?
Ренон Стюарт

@RS Мені потрібно це зробити програмно, тому що ми надалі розширимо цю власну кошик різними спеціальними параметрами, які, на мою думку, можна зробити лише за допомогою спеціального модуля.
Файяз Хаттак

Чи можете ви додати до свого коду посилання (github), тож я можу завантажити та спробувати реалізувати
Additional_options

@RS Так, будь ласка, дайте мені кілька хвилин.
Фаяз Хаттак

Відповіді:


14

Для цього ви можете скористатися функцією magento вбудованої "додаткові_операції", щоб вам не довелося редагувати шаблон електронної пошти, перегляд замовлення адміністратора, перегляд замовлення клієнта (тощо) для відображення своїх спеціальних параметрів.

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 - Копіювання параметра з quo_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 - Копіювання параметра з quo_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;
    }
}

Кошик для покупок та сторінку перегляду замовлень адміністратора

Base off Magento1 - Атрибут продукту / котирування / замовлення продукту на основі введення користувача


@renon Я спробував вище функціональність для простого продукту, і це вийшло чудово, дякую! але мені потрібно те саме для продукту, який можна налаштувати, але на сторінці кошика з'являється наступна помилка "Вибрані параметри або їх комбінація наразі недоступна" Я знаю, чому виникає ця проблема, але чи є спосіб її подолати, я маю на увазі відфільтрувати конкретні варіанти?
Наусіф

Просто використав це, і це працює як шарм. Дякую! Чи знаєте ви про будь-яку функціональність у Magento, яка дійсно дозволяє властивості на предмет (не на продукт)? Наприклад, нестандартний текст на сорочці, але, маючи декілька однакових сорочок з різними текстами. Magento тепер поєднує ці продукти в кошику, і таким чином я втрачаю ці дійсно конкретні налаштування на кожен предмет.
Юрген

@Nausif, я зіткнувся з тим же питанням, але зараз це вирішилося. Перейдіть за цією URL-адресою - magento.stackexchange.com/questions/177133/…
Kishor Hase

@renon Я використовую це, і значення відображаються в міні-кошику, кошику та касі. У мене є конфігуруваний продукт для цього. Я спробував обидва способи перетворення котирувань, але значення, які не відображаються в розділі пошти та замовлення в адміністраторі.
Rishabh Rk Rai

Якщо хтось [invalidargumentexception] unable to unserialize value.використовує json_encode та json_decode замість серіалізувати та
несеріалізувати

0

Щоб вирішити цю проблему: // Створення нового елемента кошика з однаковими значеннями параметрів додасть нову позицію замість збільшення попереднього елемента qty

Я додав після плагіна для method RepreProduct в Magento \ Quote \ Model \ Quote \ Item. У плагіні я перевіряю, чи потрібен мій додатковий параметр, і якщо це повернення потрібний результат (правда).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.