Cum să adăugați un câmp personalizat la Opțiuni în extensia Opțiuni avansate de produs

Publicat: 2020-09-08

Din acest articol, veți învăța cum să creați un câmp „GTIN” pentru opțiunile personalizate ale produsului, să îl afișați pe pagina de produs și să îl afișați în comandă.

Fără alte prelungiri, să trecem la instrucțiunile pas cu pas.

Cuprins

  • Pasul 1. Creați un nou modul
  • Pasul 2. Adăugați noul nostru câmp la baza de date
  • Pasul 3. Adăugați logica pentru a lucra cu backend
  • Pasul #4. Afișați câmpul nostru pe pagina de produs Front-end
  • Pasul #5. Adăugați datele noastre despre atribute la detaliile comenzii din baza de date
  • Pasul #6. Afișați datele pe pagina Comenzi din panoul de administrare

Pasul 1. Creați un nou modul

Am descris în detaliu cum să creați un modul în acest articol. Astfel, să omitem această parte și să trecem direct la codul de care veți avea nevoie pentru a crea un supliment:

1.compozitor.json

 { "name": "mageworx/module-optiongtin", "description": "N/A", "require": { "magento/framework" : ">=100.1.0 <101", "magento/module-catalog": ">=101.0.0 <104" }, "type": "magento2-module", "version": "1.0.0", "license": [ "OSL-3.0", "AFL-3.0" ], "autoload": { "files": [ "registration.php" ], "psr-4": { "VendorName\\OptionGtin\\": "" } } }

2.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="VendorName_OptionGtin" setup_version="1.0.0"> <sequence> <module name="Magento_Catalog"/> <module name="MageWorx_OptionBase"/> </sequence> </module> </config>

3.înregistrare.php

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

Pasul 2. Adăugați noul nostru câmp la baza de date

După ce am construit un modul gol, este timpul să creăm noul câmp „GTIN” și să îl adăugam la baza de date în tabelul corespunzător. Pe măsură ce adăugăm un câmp pentru valorile opțiunilor, vom avea nevoie de tabelul „catalog_product_option”.

Să creăm următorul fișier:

app/code/VendorName/OptionGtin/Setup/InstallSchema.php

 <?php namespace VendorName\OptionGtin\Setup; use Magento\Framework\Setup\InstallSchemaInterface; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\SchemaSetupInterface; use Magento\Framework\DB\Ddl\Table; class InstallSchema implements InstallSchemaInterface { public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) { $setup->startSetup(); $setup->getConnection()->addColumn( $setup->getTable('catalog_product_option'), 'gtin', [ 'type' => Table::TYPE_TEXT, 'nullable' => true, 'default' => null, 'comment' => 'Gtin (added by VendorName Option Gtin)', ] ); $setup->endSetup(); } }

Pasul 3. Adăugați logica pentru a lucra cu backend

Vom folosi mecanismul de modificare a grupului pentru a adăuga noul nostru câmp.

Acum, adăugați următorul fișier:

app/code/VendorName/OptionGtin/etc/adminhtml/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"> <virtualType name="MageWorx\OptionBase\Ui\DataProvider\Product\Form\Modifier\Pool"> <arguments> <argument name="modifiers" xsi:type="array"> <item name="mageworx-option-gtin" xsi:type="array"> <item name="class" xsi:type="string">VendorName\OptionGtin\Ui\DataProvider\Product\Form\Modifier\OptionGtin</item> <item name="sortOrder" xsi:type="number">72</item> </item> </argument> </arguments> </virtualType> </config>

Aici, să adăugăm modificatorul nostru la pool-ul partajat al extensiei Advanced Product Options – „MageWorx\OptionBase\Ui\DataProvider\Product\Form\Modifier\Pool”. „VendorName\OptionGtin\Ui\DataProvider\Product\Form\Modifier\OptionGtin” este modificatorul nostru de clasă.

Codul care permite adăugarea câmpului nostru la formularul app/code/VendorName/OptionGtin/Ui/DataProvider/Product/Form/Modifier/OptionGtin.php este furnizat mai jos:

 <?php namespace VendorName\OptionGtin\Ui\DataProvider\Product\Form\Modifier; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions; use Magento\Ui\Component\Form\Element\Input; use Magento\Ui\Component\Form\Element\DataType\Number; use Magento\Ui\Component\Form\Field; use MageWorx\OptionBase\Ui\DataProvider\Product\Form\Modifier\ModifierInterface; class OptionGtin extends AbstractModifier implements ModifierInterface { /** * @var array */ protected $meta = []; /** * {@inheritdoc} */ public function modifyData(array $data) { return $data; } /** * {@inheritdoc} */ public function modifyMeta(array $meta) { $this->meta = $meta; $this->addFields(); return $this->meta; } /** * Adds fields to the meta-data */ protected function addFields() { $groupCustomOptionsName = CustomOptions::GROUP_CUSTOM_OPTIONS_NAME; $optionContainerName = CustomOptions::CONTAINER_OPTION; $commonOptionContainerName = CustomOptions::CONTAINER_COMMON_NAME; // Add fields to the option $optionFeaturesFields = $this->getOptionGtinFieldsConfig(); $this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children'] [$optionContainerName]['children'][$commonOptionContainerName]['children'] = array_replace_recursive( $this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children'] [$optionContainerName]['children'][$commonOptionContainerName]['children'], $optionFeaturesFields ); } /** * The custom option fields config * * @return array */ protected function getOptionGtinFieldsConfig() { $fields['gtin'] = $this->getGtinFieldConfig(); return $fields; } /** * Get gtin field config * * @return array */ protected function getGtinFieldConfig() { return [ 'arguments' => [ 'data' => [ 'config' => [ 'label' => __('GTIN'), 'componentType' => Field::NAME, 'formElement' => Input::NAME, 'dataType' => Number::NAME, 'dataScope' => 'gtin', 'sortOrder' => 65 ], ], ], ]; } /** * Check is current modifier for the product only * * @return bool */ public function isProductScopeOnly() { return false; } /** * Get sort order of modifier to load modifiers in the right order * * @return int */ public function getSortOrder() { return 32; } }

Acum, să încercăm să instalăm extensia și să verificăm dacă totul este afișat:

  • Modulul php bin/magento: activați VendorName_OptionGtin
  • php bin/magento setup:upgrade
  • php bin/magento cache:flush

Noul nostru câmp a fost adăugat cu succes:

Cum să adăugați un câmp personalizat la Opțiuni avansate de produs | Blogul Mageworx

Pasul #4. Afișați câmpul nostru pe pagina de produs Front-end

Extensia Mageworx Advanced Product Options are deja totul pentru a afișa și a lucra cu atributele pe care le adaugă modulul nostru. Tot ce trebuie să facem este să adăugăm noul atribut la setul de date partajat.

Modulul nostru MageWorx_OptionBase folosește deja metoda getExtendedOptionsConfig() . Colectează și afișează toate atributele personalizate într-un bloc pe front-end. Deschideți clasa app/code/MageWorx/OptionBase/Block/Product/View/Options.php pentru a vedea cum este implementată.

Să începem cu crearea unui model cu atributul nostru:

app/code/VendorName/OptionGtin/Model/Attriburte/Option/Gtin.php

 <?php namespace VendorName\OptionGtin\Model\Attribute\Option; use MageWorx\OptionBase\Model\Product\Option\AbstractAttribute; class Gtin extends AbstractAttribute { /** * @return string */ public function getName() { return 'gtin'; } }

Acum, utilizați mecanismul de „injectare a dependenței” și adăugați atributul nostru la setul de date de atribute partajate al extensiei Opțiuni avansate de produs.

app/code/VendorName/OptionGtin/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"> <!-- Data --> <type name="MageWorx\OptionBase\Model\Product\Option\Attributes"> <arguments> <argument name="data" xsi:type="array"> <item name="gtin" xsi:type="object">VendorName\OptionGtin\Model\Attribute\Option\Gtin</item> </argument> </arguments> </type> </config>

Cu alte cuvinte, prin deschiderea MageWorx\OptionBase\Model\Product\Option\Attributes , veți vedea că pur și simplu colectează toate obiectele atribute în setul de date partajat.

Pentru a afișa datele noului nostru atribut „GTIN”, am decis să folosim funcția firstrun() din app/code/MageWorx/OptionFeatures/view/base/web/js/catalog/product/features.js . Are deja toată implementarea necesară care se potrivește cel mai bine exemplului nostru. Pentru a evita suprascrierea întregului fișier, vom aplica mecanismul „JavaScript mixins”, care ne va ajuta să schimbăm doar funcția necesară.

Creați următorul fișier și definiți mix-ul nostru acolo: app/code/VendorName/OptionGtin/view/frontend/requirejs-config.js

 var config = { config: { mixins: { 'MageWorx_OptionFeatures/js/catalog/product/features': { 'VendorName_OptionGtin/js/catalog/product/features-gtin-mixin' : true } } } };

Aici, MageWorx_OptionFeatures/js/catalog/product/features este rădăcina fișierului nostru, metoda pe care trebuie să o rescriem. VendorName_OptionGtin/js/catalog/product/features-gtin-mixin este fișierul, unde vom rescrie metoda.

Deci, să-l creăm: app/code/VendorName/OptionGtin/view/frontend/web/js/catalog/product/features-gtin-mixin.js

 define([ 'jquery', 'jquery/ui', 'mage/utils/wrapper' ], function ($, wrapper) { 'use strict'; return function (widget) { $.widget('mageworx.optionFeatures', widget, { /** * Triggers one time at first run (from base.js) * @param optionConfig * @param productConfig * @param base * @param self */ firstRun: function firstRun(optionConfig, productConfig, base, self) { //shareable link $('#mageworx_shareable_hint_icon').qtip({ content: { text: this.options.shareable_link_hint_text }, style: { classes: 'qtip-light' }, position: { target: false } }); $('#mageworx_shareable_link').on('click', function () { try { self.copyTextToClipboard(self.getShareableLink(base)); $('.mageworx-shareable-link-container').hide(); $('.mageworx-shareable-link-success-container').show(); setTimeout(function () { $('.mageworx-shareable-link-container').show(); $('.mageworx-shareable-link-success-container').hide(); }, 2000); } catch (error) { console.log('Something goes wrong. Unable to copy'); } }); setTimeout(function () { // Qty input $('.mageworx-option-qty').each(function () { $(this).on('change', function () { var optionInput = $("[data-selector='" + $(this).attr('data-parent-selector') + "']"); optionInput.trigger('change'); }); }); }, 500); // Option\Value Description & tooltip var extendedOptionsConfig = typeof base.options.extendedOptionsConfig != 'undefined' ? base.options.extendedOptionsConfig : {}; for (var option_id in optionConfig) { if (!optionConfig.hasOwnProperty(option_id)) { continue; } var description = extendedOptionsConfig[option_id]['description'], gtin = extendedOptionsConfig[option_id]['gtin'], gtinTitle = "Global Trade Item Number: ", $option = base.getOptionHtmlById(option_id); if (1 > $option.length) { console.log('Empty option container for option with id: ' + option_id); continue; } var $label = $option.find('label'); if(gtin != null && gtin.length > 0) { if ($label.length > 0) { $label .first() .after($('<p class="option-gtin-text"><span>' + gtinTitle + '</span>' + gtin + '</p>')); } else { $label = $option.find('span'); $label .first() .parent() .after($('<p class="option-gtin-text"><span>' + gtinTitle + '</span>' + gtin + '</p>')); } } if (this.options.option_description_enabled && !_.isEmpty(extendedOptionsConfig[option_id]['description'])) { if (this.options.option_description_mode == this.options.option_description_modes.tooltip) { var $element = $option.find('label span') .first(); if ($element.length == 0) { $element = $option.find('fieldset legend span') .first(); } $element.css('border-bottom', '1px dotted black'); $element.qtip({ content: { text: description }, style: { classes: 'qtip-light' }, position: { target: false } }); } else if (this.options.option_description_mode == this.options.option_description_modes.text) { if ($label.length > 0) { $label .first() .after($('<p class="option-description-text">' + description + '</p>')); } else { $label = $option.find('span'); $label .first() .parent() .after($('<p class="option-description-text">' + description + '</p>')); } } else { console.log('Unknown option mode'); } } if (this.options.value_description_enabled) { this._addValueDescription($option, optionConfig, extendedOptionsConfig); } } } }); return $.mageworx.optionFeatures; }; });

În general, putem rula următoarele comenzi acum:

  • php bin/magento cache:flush
  • php bin/magento setup:static-content:deploy (numai pentru modul producție)

și vezi ce avem. Dar mai întâi, adăugați câteva stiluri noului nostru atribut și faceți-l să arate frumos pe front-end.

Creați un aspect și definiți noul nostru fișier de stiluri acolo: app/code/VendorName/OptionGtin/view/frontend/layout/catalog_product_view.xml

 <?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <head> <css src="VendorName_OptionGtin::css/gtin.css"/> </head> </page>

Este timpul să creați un fișier de stiluri: app/code/VendorName/OptionGtin/view/frontend/web/css/gtin.css

 .option-gtin-text span { color: #6cc308; font-weight: 700; }

Acum, să rulăm comenzile descrise anterior și să verificăm rezultatele:

Cum să adăugați un câmp personalizat la Opțiuni avansate de produs | Blogul Mageworx

Pasul #5. Adăugați datele noastre despre atribute la detaliile comenzii din baza de date

Când un client face o achiziție, se creează o comandă. Detaliile despre articolele adăugate sunt incluse în tabelul sales_order_item . Acest tabel are câmpul product_options care conține informații despre parametrii selectați ai unui articol adăugat. Acolo ar trebui să adăugăm datele noului nostru atribut.

Pe măsură ce o comandă este creată, evenimentul sales_quote_address_collect_totals_before este declanșat. Îl vom folosi pentru a adăuga datele noastre la opțiunile de produs.

Să definim evenimentul creând: app/code/VendorName/OptionGtin/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="sales_quote_address_collect_totals_before"> <observer name="mageworx_optiongtin_add_gtin_to_order" instance="VendorName\OptionGtin\Observer\AddGtinToOrder" /> </event> </config>

Apoi, creați observatorul nostru: app/code/VendorName/OptionGtin/Observer/AddGtinToOrder.php

 <?php namespace VendorName\OptionGtin\Observer; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Catalog\Model\ProductRepository as ProductRepository; use MageWorx\OptionBase\Helper\Data as BaseHelper; class AddGtinToOrder implements ObserverInterface { /** * @var BaseHelper */ protected $baseHelper; protected $productRepository; /** * AddGtinToOrder constructor. * @param BaseHelper $baseHelper * @param ProductRepository $productRepository */ public function __construct( BaseHelper $baseHelper, ProductRepository $productRepository ) { $this->baseHelper = $baseHelper; $this->productRepository = $productRepository; } /** * Add product to quote action * Processing: gtin * * @param Observer $observer * @return $this */ public function execute(Observer $observer) { $quoteItems = $observer->getQuote()->getAllItems(); /** @var \Magento\Quote\Model\Quote\Item $quoteItem */ foreach ($quoteItems as $quoteItem) { $buyRequest = $quoteItem->getBuyRequest(); $optionIds = array_keys($buyRequest->getOptions()); $productOptions = $this->productRepository->getById($buyRequest->getProduct())->getOptions(); $quoteItemOptionGtins = []; $optionGtins = []; foreach ($productOptions as $option) { if ($option->getGtin()) { $quoteItemOptionGtins[$option->getOptionId()] = $option->getGtin(); } } foreach ($optionIds as $optionId) { $optionGtins[$optionId] = $optionId; } $optionGtins = array_intersect_key($quoteItemOptionGtins, $optionGtins); $infoBuyRequest = $quoteItem->getOptionByCode('info_buyRequest'); $buyRequest->setData('gtin', $optionGtins); $infoBuyRequest->setValue($this->baseHelper->encodeBuyRequestValue($buyRequest->getData())); $quoteItem->addOption($infoBuyRequest); } } }

Aici, cu ajutorul observatorului, obținem lista tuturor articolelor din comandă și adăugăm datele atributului nostru „GTIN” la așa-numitul $infoBuyRequest .

Pentru a verifica dacă totul a fost efectuat corect, creați o comandă cu produsul, care opțiuni au date „GTIN”. Puteți verifica dacă datele au fost adăugate în sales_order_item table -> câmpul product_options :

Cum să adăugați un câmp personalizat la Opțiuni avansate de produs | Blogul Mageworx

Pasul #6. Afișați datele pe pagina Comenzi din panoul de administrare

Există diferite mijloace pentru a afișa informațiile necesare în șablonul gata. De exemplu, folosind „js”. Am lucrat cu „js” în acest articol. Să lucrăm cu șabloanele în sine pentru o schimbare și să încercăm să le rescriem!

Schimbați app/code/VendorName/OptionGtin/etc/adminhtml/di.xml anterior adăugând pluginul acolo:

 <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <virtualType name="MageWorx\OptionBase\Ui\DataProvider\Product\Form\Modifier\Pool"> <arguments> <argument name="modifiers" xsi:type="array"> <item name="mageworx-option-gtin" xsi:type="array"> <item name="class" xsi:type="string">VendorName\OptionGtin\Ui\DataProvider\Product\Form\Modifier\OptionGtin</item> <item name="sortOrder" xsi:type="number">72</item> </item> </argument> </arguments> </virtualType> <!-- Plugins--> <type name="Magento\Sales\Block\Adminhtml\Items\Column\DefaultColumn"> <plugin name="mageworx-optiongtin-add-default-column" type="VendorName\OptionGtin\Plugin\AddDefaultColumn" sortOrder="5" disabled="false" /> </type> </config>

Creați pluginul în sine:

app/code/VendorName/OptionGtin/Plugin/AddDefaultColumn.php

 <?php namespace VendorName\OptionGtin\Plugin; class AddDefaultColumn { /** * @param \Magento\Sales\Block\Adminhtml\Items\Column\DefaultColumn $subject * @param $result * @return array */ public function afterGetOrderOptions(\Magento\Sales\Block\Adminhtml\Items\Column\DefaultColumn $subject, $result) { if ($options = $subject->getItem()->getProductOptions()) { if (isset($result)) { foreach ($result as &$option) { if (array_key_exists($option['option_id'], $options['info_buyRequest']['gtin'])) { $option['gtin'] = $options['info_buyRequest']['gtin'][$option['option_id']]; } } } } return $result; } }

Acest plugin adaugă informații despre noul nostru atribut pentru opțiunile de comandă, pentru care există aceste date.

vendor/magento/module-sales/view/adminhtml/templates/items/column/name.phtml este responsabil pentru afișarea informațiilor despre opțiunile produsului pe pagina de comandă din panoul de administrare.

Să-l rescriem pentru a afișa „GTIN-ul nostru”. Pentru asta, trebuie să rescriem blocul „column_name”, sau mai degrabă șablonul acestuia. Creați un aspect și un șablon:

app/code/VendorName/OptionGtin/view/adminhtml/layout/sales_order_view.xml

 <?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="column_name"> <action method="setTemplate"> <argument name="template" xsi:type="string">VendorName_OptionGtin::items/column/name.phtml</argument> </action> </referenceBlock> </body> </page>

app/code/VendorName/OptionGtin/view/adminhtml/templates/items/column/name.phtml

 <?php /* @var $block \Magento\Sales\Block\Adminhtml\Items\Column\Name */ ?> <?php if ($_item = $block->getItem()) : ?> <div class="product-title"> <?= $block->escapeHtml($_item->getName()) ?> </div> <div class="product-sku-block"> <span><?= $block->escapeHtml(__('SKU'))?>:</span> <?= /* @noEscape */ implode('<br />', $this->helper(\Magento\Catalog\Helper\Data::class)->splitSku($block->escapeHtml($block->getSku()))) ?> </div> <?php if ($block->getOrderOptions()) : ?> <dl class="item-options"> <?php foreach ($block->getOrderOptions() as $_option) : ?> <dt><?= $block->escapeHtml($_option['label']) ?>:</dt> <dd> <?php if (isset($_option['custom_view']) && $_option['custom_view']) : ?> <?= /* @noEscape */ $block->getCustomizedOptionValue($_option) ?> <?php else : ?> <?php $optionValue = $block->getFormattedOption($_option['value']); ?> <?php $dots = 'dots' . uniqid(); ?> <?php $ . uniqid(); ?> <?= $block->escapeHtml($optionValue['value'], ['a', 'br']) ?><?php if (isset($optionValue['remainder']) && $optionValue['remainder']) : ?> <span> ...</span> <span><?= $block->escapeHtml($optionValue['remainder'], ['a']) ?></span> <script> require(['prototype'], function() { $('<?= /* @noEscape */ $id; ?>').hide(); $('<?= /* @noEscape */ $id; ?>').up().observe('mouseover', function(){$('<?= /* @noEscape */ $id; ?>').show();}); $('<?= /* @noEscape */ $id; ?>').up().observe('mouseover', function(){$('<?= /* @noEscape */ $dots; ?>').hide();}); $('<?= /* @noEscape */ $id; ?>').up().observe('mouseout', function(){$('<?= /* @noEscape */ $id; ?>').hide();}); $('<?= /* @noEscape */ $id; ?>').up().observe('mouseout', function(){$('<?= /* @noEscape */ $dots; ?>').show();}); }); </script> <?php endif; ?> <?php endif; ?> </dd> <dt> <?php if (isset($_option['gtin']) && $_option['gtin']) : ?> <span>GTIN:</span> <?php endif; ?> </dt> <dd> <?php if (isset($_option['gtin']) && $_option['gtin']) : ?> <span> <?= $block->escapeHtml($_option['gtin']) ?></span> <?php endif; ?> </dd> <?php endforeach; ?> </dl> <?php endif; ?> <?= $block->escapeHtml($_item->getDescription()) ?> <?php endif; ?>

Dacă totul a fost efectuat corect, șters și compilat, atunci veți vedea următorul rezultat:

Cum să adăugați un câmp personalizat la Opțiuni avansate de produs | Blogul Mageworx

Sperăm să găsiți acest articol de ajutor. Dacă aveți dificultăți sau probleme, nu ezitați să ne anunțați în câmpul de comentarii de mai jos.

Rezervați o demonstrație live cu Mageworx