Magento 2 Dodaj listę rozwijaną do metody wysyłki

16

Opracowuję metodę wysyłki dla jakiejś firmy logistycznej. Ta firma ma wiele biur, w których klient może otrzymać swoje zamówienie. Mogę uzyskać listę biur według API w API, ale nie wiem, jak lepiej reprezentują ten krok?

Na razie po prostu ustawiłem nowy \Magento\Quote\Model\Quote\Address\RateResult\Method w każdym biurze w mieście, w dużym mieście jest to liczba> 100 i myślę, że nie jest zbyt dobrze ustawić 100 linii w kasie.

Będzie to moduł publiczny dla innego projektu kasy, więc jak mogę wyświetlić w pobliżu wybranej metody wysyłki listę rozwijaną z listą biur oraz ustawić cenę i metodę po wybraniu przez użytkownika jednej.

Jamess Moriarty
źródło
@Zefiryn Uważam ten post za bardzo interesujący, ale mam pytanie, czy muszę pokazać w wybranych nie biurach, ale sklepach znajdujących się w module Amasty'ego, jak zrobiłbym drugą część tego postu? Mam na myśli: gdzie jest miejsce, w którym nazywam pomocnika Amasty, aby wypełnić komponent xml „vendor_carrier_form”? Dzięki
maverickk89,
Jeśli masz nowe pytanie, zadaj je, klikając przycisk Zadaj pytanie . Dołącz link do tego pytania, jeśli pomaga to w zapewnieniu kontekstu. - Z recenzji
Jai
to nie jest nowe pytanie, ale odmiana sposobu, w jaki Zefiryn… ponieważ użyłem pierwszej części postu
maverickk89,

Odpowiedzi:

17

Kasa Magento nie obsługuje żadnego rodzaju danych dodatkowych dotyczących sposobu wysyłki. Ale zapewnia shippingAdditionalblok w kasie, którego można użyć do tego. Poniższe rozwiązanie będzie działać w przypadku standardowej kasy Magento.

Najpierw przygotujmy nasz pojemnik, w którym możemy umieścić jakąś formę. Aby to zrobić, utwórz plik wview/frontend/layout/checkout_index_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.root">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <item name="components" xsi:type="array">
                        <item name="checkout" xsi:type="array">
                            <item name="children" xsi:type="array">
                                <item name="steps" xsi:type="array">
                                    <item name="children" xsi:type="array">
                                        <item name="shipping-step" xsi:type="array">
                                            <item name="children" xsi:type="array">
                                                <item name="shippingAddress" xsi:type="array">
                                                    <item name="children" xsi:type="array">
                                                        <item name="shippingAdditional" xsi:type="array">
                                                            <item name="component" xsi:type="string">uiComponent</item>
                                                            <item name="displayArea" xsi:type="string">shippingAdditional</item>
                                                            <item name="children" xsi:type="array">
                                                                <item name="vendor_carrier_form" xsi:type="array">
                                                                    <item name="component" xsi:type="string">Vendor_Module/js/view/checkout/shipping/form</item>
                                                                </item>
                                                            </item>
                                                        </item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

Teraz utwórz plik, w Vendor/Module/view/frontend/web/js/view/checkout/shipping/form.jsktórym wyrenderuje szablon nokaut. Jego treść wygląda następująco

define([
    'jquery',
    'ko',
    'uiComponent',
    'Magento_Checkout/js/model/quote',
    'Magento_Checkout/js/model/shipping-service',
    'Vendor_Module/js/view/checkout/shipping/office-service',
    'mage/translate',
], function ($, ko, Component, quote, shippingService, officeService, t) {
    'use strict';

    return Component.extend({
        defaults: {
            template: 'Vendor_Module/checkout/shipping/form'
        },

        initialize: function (config) {
            this.offices = ko.observableArray();
            this.selectedOffice = ko.observable();
            this._super();
        },

        initObservable: function () {
            this._super();

            this.showOfficeSelection = ko.computed(function() {
                return this.ofices().length != 0
            }, this);

            this.selectedMethod = ko.computed(function() {
                var method = quote.shippingMethod();
                var selectedMethod = method != null ? method.carrier_code + '_' + method.method_code : null;
                return selectedMethod;
            }, this);

            quote.shippingMethod.subscribe(function(method) {
                var selectedMethod = method != null ? method.carrier_code + '_' + method.method_code : null;
                if (selectedMethod == 'carrier_method') {
                    this.reloadOffices();
                }
            }, this);

            this.selectedOffice.subscribe(function(office) {
                if (quote.shippingAddress().extensionAttributes == undefined) {
                    quote.shippingAddress().extensionAttributes = {};
                }
                quote.shippingAddress().extensionAttributes.carrier_office = office;
            });


            return this;
        },

        setOfficeList: function(list) {
            this.offices(list);
        },

        reloadOffices: function() {
            officeService.getOfficeList(quote.shippingAddress(), this);
            var defaultOffice = this.offices()[0];
            if (defaultOffice) {
                this.selectedOffice(defaultOffice);
            }
        },

        getOffice: function() {
            var office;
            if (this.selectedOffice()) {
                for (var i in this.offices()) {
                    var m = this.offices()[i];
                    if (m.name == this.selectedOffice()) {
                        office = m;
                    }
                }
            }
            else {
                office = this.offices()[0];
            }

            return office;
        },

        initSelector: function() {
            var startOffice = this.getOffice();
        }
    });
});

Ten plik używa szablonu nokaut, w którym należy umieścić Vendor/Module/view/frontend/web/template/checkout/shipping/form.html

<div id="carrier-office-list-wrapper" data-bind="visible: selectedMethod() == 'carrier_method'">
    <p data-bind="visible: !showOfficeSelection(), i18n: 'Please provide postcode to see nearest offices'"></p>
    <div data-bind="visible: showOfficeSelection()">
        <p>
            <span data-bind="i18n: 'Select pickup office.'"></span>
        </p>
        <select id="carrier-office-list" data-bind="options: offices(),
                                            value: selectedOffice,
                                            optionsValue: 'name',
                                            optionsText: function(item){return item.location + ' (' + item.name +')';}">
        </select>
    </div>
</div>

Mamy teraz pole wyboru, które będzie widoczne, gdy nasza metoda (zdefiniowana przez kod) zostanie wybrana w tabeli metod wysyłki. Czas wypełnić go kilkoma opcjami. Ponieważ wartości zależą od adresu, najlepszym sposobem jest utworzenie punktu końcowego odpoczynku, który zapewni dostępne opcje. WVendor/Module/etc/webapi.xml

<?xml version="1.0"?>

<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">

    <!-- Managing Office List on Checkout page -->
    <route url="/V1/module/get-office-list/:postcode/:city" method="GET">
        <service class="Vendor\Module\Api\OfficeManagementInterface" method="fetchOffices"/>
        <resources>
            <resource ref="anonymous" />
        </resources>
    </route>
</routes>

Teraz zdefiniuj interfejs Vendor/Module/Api/OfficeManagementInterface.phpjako

namespace Vendor\Module\Api;

interface OfficeManagementInterface
{

    /**
     * Find offices for the customer
     *
     * @param string $postcode
     * @param string $city
     * @return \Vendor\Module\Api\Data\OfficeInterface[]
     */
    public function fetchOffices($postcode, $city);
}

Zdefiniuj interfejs dla danych biurowych w Vendor\Module\Api\Data\OfficeInterface.php. Interfejs ten będzie używany przez moduł webapi do filtrowania danych wyjściowych, dlatego należy zdefiniować wszystko, co należy dodać do odpowiedzi.

namespace Vendor\Module\Api\Data;

/**
 * Office Interface
 */
interface OfficeInterface
{
    /**
     * @return string
     */
    public function getName();

    /**
     * @return string
     */
    public function getLocation();
}

Czas na faktyczne zajęcia. Zacznij od tworzenia preferencji dla wszystkich interfejsów wVendor/Module/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">
    <preference for="Vendor\Module\Api\OfficeManagementInterface" type="Vendor\Module\Model\OfficeManagement" />
    <preference for="Vendor\Module\Api\Data\OfficeInterface" type="Vendor\Module\Model\Office" />
</config>

Teraz stwórz Vendor\Module\Model\OfficeManagement.phpklasę, która faktycznie wykona logikę pobierania danych.

namespace Vednor\Module\Model;

use Vednor\Module\Api\OfficeManagementInterface;
use Vednor\Module\Api\Data\OfficeInterfaceFactory;

class OfficeManagement implements OfficeManagementInterface
{
    protected $officeFactory;

    /**
     * OfficeManagement constructor.
     * @param OfficeInterfaceFactory $officeInterfaceFactory
     */
    public function __construct(OfficeInterfaceFactory $officeInterfaceFactory)
    {
        $this->officeFactory = $officeInterfaceFactory;
    }

    /**
     * Get offices for the given postcode and city
     *
     * @param string $postcode
     * @param string $limit
     * @return \Vendor\Module\Api\Data\OfficeInterface[]
     */
    public function fetchOffices($postcode, $city)
    {
        $result = [];
        for($i = 0, $i < 4;$i++) {
            $office = $this->officeFactory->create();
            $office->setName("Office {$i}");
            $office->setLocation("Address {$i}");
            $result[] = $office;
        }

        return $result;
    }
}

I wreszcie klasa dla OfficeInterfacewVendor/Module/Model/Office.php

namespace Vendor\Module\Model;

use Magento\Framework\DataObject;
use Vendor\Module\Api\Data\OfficeInterface;

class Office extends DataObject implements OfficeInterface
{
    /**
     * @return string
     */
    public function getName()
    {
        return (string)$this->_getData('name');
    }

    /**
     * @return string
     */
    public function getLocation()
    {
        return (string)$this->_getData('location');
    }
}

Powinno to pokazać pole wyboru i zaktualizować je po zmianie adresu. Ale brakuje nam jeszcze jednego elementu do manipulowania interfejsem. Musimy stworzyć funkcję, która wywoła punkt końcowy. Wywołanie do niego jest już uwzględnione Vendor/Module/view/frontend/web/js/view/checkout/shipping/form.jsi jest to Vendor_Module/js/view/checkout/shipping/office-serviceklasa, do której powinien przejść Vendor/Module/view/frontend/web/js/view/checkout/shipping/office-service.jsnastępujący kod:

define(
    [
        'Vendor_Module/js/view/checkout/shipping/model/resource-url-manager',
        'Magento_Checkout/js/model/quote',
        'Magento_Customer/js/model/customer',
        'mage/storage',
        'Magento_Checkout/js/model/shipping-service',
        'Vendor_Module/js/view/checkout/shipping/model/office-registry',
        'Magento_Checkout/js/model/error-processor'
    ],
    function (resourceUrlManager, quote, customer, storage, shippingService, officeRegistry, errorProcessor) {
        'use strict';

        return {
            /**
             * Get nearest machine list for specified address
             * @param {Object} address
             */
            getOfficeList: function (address, form) {
                shippingService.isLoading(true);
                var cacheKey = address.getCacheKey(),
                    cache = officeRegistry.get(cacheKey),
                    serviceUrl = resourceUrlManager.getUrlForOfficeList(quote);

                if (cache) {
                    form.setOfficeList(cache);
                    shippingService.isLoading(false);
                } else {
                    storage.get(
                        serviceUrl, false
                    ).done(
                        function (result) {
                            officeRegistry.set(cacheKey, result);
                            form.setOfficeList(result);
                        }
                    ).fail(
                        function (response) {
                            errorProcessor.process(response);
                        }
                    ).always(
                        function () {
                            shippingService.isLoading(false);
                        }
                    );
                }
            }
        };
    }
);

Wykorzystuje 2 kolejne pliki js. Vendor_Module/js/view/checkout/shipping/model/resource-url-managertworzy adres URL do punktu końcowego i jest dość prosty

define(
    [
        'Magento_Customer/js/model/customer',
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/model/url-builder',
        'mageUtils'
    ],
    function(customer, quote, urlBuilder, utils) {
        "use strict";
        return {
            getUrlForOfficeList: function(quote, limit) {
                var params = {postcode: quote.shippingAddress().postcode, city: quote.shippingAddress().city};
                var urls = {
                    'default': '/module/get-office-list/:postcode/:city'
                };
                return this.getUrl(urls, params);
            },

            /** Get url for service */
            getUrl: function(urls, urlParams) {
                var url;

                if (utils.isEmpty(urls)) {
                    return 'Provided service call does not exist.';
                }

                if (!utils.isEmpty(urls['default'])) {
                    url = urls['default'];
                } else {
                    url = urls[this.getCheckoutMethod()];
                }
                return urlBuilder.createUrl(url, urlParams);
            },

            getCheckoutMethod: function() {
                return customer.isLoggedIn() ? 'customer' : 'guest';
            }
        };
    }
);

Vendor_Module/js/view/checkout/shipping/model/office-registryjest sposobem na utrzymanie wyniku w lokalnej pamięci. Jego kod to:

define(
    [],
    function() {
        "use strict";
        var cache = [];
        return {
            get: function(addressKey) {
                if (cache[addressKey]) {
                    return cache[addressKey];
                }
                return false;
            },
            set: function(addressKey, data) {
                cache[addressKey] = data;
            }
        };
    }
);

Ok, więc powinniśmy wszyscy pracować nad frontendem. Ale teraz jest inny problem do rozwiązania. Ponieważ kasa nie wie nic o tym formularzu, nie wyśle ​​wyniku wyboru do backendu. Aby tak się stało, musimy użyć extension_attributesfunkcji. W Magento2 jest to sposób na poinformowanie systemu, że niektóre dodatkowe dane powinny znajdować się w pozostałych wywołaniach. Bez niego magento odfiltrowałoby te dane i nigdy nie dotarłyby do kodu.

Więc najpierw Vendor/Module/etc/extension_attributes.xmlzdefiniuj:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Quote\Api\Data\AddressInterface">
        <attribute code="carrier_office" type="string"/>
    </extension_attributes>
</config>

Ta wartość jest już wstawiona do żądania form.jsz this.selectedOffice.subscribe()definicji. Tak więc powyższa konfiguracja przejdzie tylko przy wejściu. Aby pobrać go w kodzie, utwórz wtyczkęVendor/Module/etc/di.xml

<type name="Magento\Quote\Model\Quote\Address">
    <plugin name="inpost-address" type="Vendor\Module\Quote\AddressPlugin" sortOrder="1" disabled="false"/>
</type>

Wewnątrz tej klasy

namespace Vendor\Module\Plugin\Quote;

use Magento\Quote\Model\Quote\Address;
use Vendor\Module\Model\Carrier;

class AddressPlugin
{
    /**
     * Hook into setShippingMethod.
     * As this is magic function processed by __call method we need to hook around __call
     * to get the name of the called method. after__call does not provide this information.
     *
     * @param Address $subject
     * @param callable $proceed
     * @param string $method
     * @param mixed $vars
     * @return Address
     */
    public function around__call($subject, $proceed, $method, $vars)
    {
        $result = $proceed($method, $vars);
        if ($method == 'setShippingMethod'
            && $vars[0] == Carrier::CARRIER_CODE.'_'.Carrier::METHOD_CODE
            && $subject->getExtensionAttributes()
            && $subject->getExtensionAttributes()->getCarrierOffice()
        ) {
            $subject->setCarrierOffice($subject->getExtensionAttributes()->getCarrierOffice());
        }
        elseif (
            $method == 'setShippingMethod'
            && $vars[0] != Carrier::CARRIER_CODE.'_'.Carrier::METHOD_CODE
        ) {
            //reset office when changing shipping method
            $subject->getCarrierOffice(null);
        }
        return $result;
    }
}

Oczywiście, gdzie zaoszczędzisz wartość zależy całkowicie od twoich wymagań. Powyższy kod wymagałby utworzenia dodatkowej kolumny carrier_officew quote_addressi sales_addresstabel oraz zdarzenia (w Vendor/Module/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_model_service_quote_submit_before">
        <observer name="copy_carrier_office" instance="Vendor\Module\Observer\Model\Order" />
    </event>
</config>

Spowodowałoby to skopiowanie danych zapisanych w adresie oferty na adres sprzedaży.

Napisałem to dla mojego modułu dla polskiego operatora InPost, więc zmieniłem niektóre nazwy, które mogą złamać kod, ale mam nadzieję, że da ci to, czego potrzebujesz.

[EDYTOWAĆ]

Model nośnika zapytany przez @sangan

namespace Vendor\Module\Model;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Phrase;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Shipping\Model\Carrier\AbstractCarrier;
use Magento\Shipping\Model\Carrier\CarrierInterface;
use Magento\Shipping\Model\Simplexml\ElementFactory;

class Carrier extends AbstractCarrier implements CarrierInterface
{
    const CARRIER_CODE = 'mycarier';

    const METHOD_CODE = 'mymethod';

    /** @var string */
    protected $_code = self::CARRIER_CODE;

    /** @var bool */
    protected $_isFixed = true;

    /**
     * Prepare stores to show on frontend
     *
     * @param RateRequest $request
     * @return \Magento\Framework\DataObject|bool|null
     */
    public function collectRates(RateRequest $request)
    {
        if (!$this->getConfigData('active')) {
            return false;
        }

        /** @var \Magento\Shipping\Model\Rate\Result $result */
        $result = $this->_rateFactory->create();

        /** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
        $method = $this->_rateMethodFactory->create();
        $method->setCarrier($this->_code);
        $method->setCarrierTitle($this->getConfigData('title'));

        $price = $this->getFinalPriceWithHandlingFee(0);
        $method->setMethod(self::METHOD_CODE);
        $method->setMethodTitle(new Phrase('MyMethod'));
        $method->setPrice($price);
        $method->setCost($price);
        $result->append($method);;

        return $result;
    }


    /**
     * @return array
     */
    public function getAllowedMethods()
    {
        $methods = [
            'mymethod' => new Phrase('MyMethod')
        ];
        return $methods;
    }
}
Zefiryn
źródło
Dziękuję za twoją rozszerzoną odpowiedź, postaram się rozwiązać problem za pomocą Twojej metody i odpowiem z wynikiem w tych dniach.
Siarhey Uchukhlebau,
@Zefiryn Stworzyłem niestandardową metodę wysyłki, poniżej wyświetli listę rozwijaną zawierającą numery kont wysyłkowych klienta (utworzono niestandardowy atrybut klienta), więc jeśli muszę wyświetlić tę listę rozwijaną, ile procent twojego kodu będzie pomocne? Co powinienem odebrać z kodu, który podałeś?
Shireen N,
@shireen Powiedziałbym, że około 70%. Musisz zmienić część, w której pobiera maszyny na numery kont. Tak więc definicja interfejsu API będzie nieco inna, a jej częścią będzie js
Zefiryn
próbowałem tego modułu ... ale nie pokazuje żadnych zmian, więc proszę udostępnić działający moduł. jeśli jakikolwiek
sangan
po dodaniu udanego modułu .. w kasie ajax ładowanie ciągłe .. w konsoli błąd pokazujący jak poniżej: wymagany.js: 166 Nieprzechwycony błąd: Błąd skryptu dla: Moduł_dostawcy / js / view / Checkout / shipping / model / office-register. requjs.org/docs/errors.html#scripterror
sangan
2

Dodaję nową odpowiedź, aby rozwinąć to, co zostało już wcześniej dostarczone, ale bez zniekształcania go.

Oto trasa, która się QuoteAddressPluginzaczepiała:

1. Magento\Checkout\Api\ShippingInformationManagementInterface::saveAddressInformation()
2. Magento\Quote\Model\QuoteRepository::save() 
3. Magento\Quote\Model\QuoteRepository\SaveHandler::save() 
4. Magento\Quote\Model\QuoteRepository\SaveHandler::processShippingAssignment() 
5. Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentPersister::save()
6. Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentProcessor::save()
7. Magento\Quote\Model\Quote\ShippingAssignment\ShippingProcessor::save()
8. Magento\Quote\Model\ShippingMethodManagement::apply() 

Ostatnią metodą było wywołanie, Magento\Quote\Model\Quote\Address::setShippingMethod()które było wywołaniem, Magento\Quote\Model\Quote\Address::__call()którego użyłem. W tej chwili znalazłem lepsze miejsce na wtyczkę, to jest Magento\Quote\Model\ShippingAssignment::setShipping()metoda. Tak więc część wtyczki można przepisać na:

<type name="Magento\Quote\Model\ShippingAssignment">
    <plugin name="carrier-office-plugin" type="Vendor\Module\Plugin\Quote\ShippingAssignmentPlugin" sortOrder="1" disabled="false"/>
</type>

i sama wtyczka:

namespace Vednor\Module\Plugin\Quote;

use Magento\Quote\Api\Data\AddressInterface;
use Magento\Quote\Api\Data\ShippingInterface;
use Magento\Quote\Model\ShippingAssignment;
use Vendor\Module\Model\Carrier;

/**
 * ShippingAssignmentPlugin
 */
class ShippingAssignmentPlugin
{
    /**
     * Hook into setShipping.
     *
     * @param ShippingAssignment $subject
     * @param ShippingInterface $value
     * @return Address
     */
    public function beforeSetShipping($subject, ShippingInterface $value)
    {
        $method = $value->getMethod();
        /** @var AddressInterface $address */
        $address = $value->getAddress();
        if ($method === Carrier::CARRIER_CODE.'_'.Carrier::METHOD_CODE
            && $address->getExtensionAttributes()
            && $address->getExtensionAttributes()->getCarrierOffice()
        ) {
            $address->setCarrierOffice($address->getExtensionAttributes()->getCarrierOffice());
        }
        elseif ($method !== Carrier::CARRIER_CODE.'_'.Carrier::METHOD_CODE) {
            //reset inpost machine when changing shipping method
            $address->setCarrierOffice(null);
        }
        return [$value];
    }
}
Zefiryn
źródło
1

@Zefiryn, natknąłem się na problem z: quote.shippingAddress().extensionAttributes.carrier_office = office;

Kiedy wchodzę do kasy po raz pierwszy (nowe okno prywatne) jako gość (ale to samo dzieje się z zarejestrowanym klientem), atrybut biura nie jest zapisywany w bazie danych po pierwszym „Dalej”. Chociaż w konsoli widzę prawidłowe dane wyjściowe dla:console.log(quote.shippingAddress().extensionAttributes.carrier_office);

Gdy wrócę do pierwszej strony kasy i ponownie wybiorę biuro, zostanie ono zapisane. Co może być przyczyną takiego zachowania?

Próbowałem użyć: address.trigger_reload = new Date().getTime(); rateRegistry.set(address.getKey(), null); rateRegistry.set(address.getCacheKey(), null); quote.shippingAddress(address);

ale bez powodzenia ...

użytkownik2089098
źródło
0

@Zefiryn, Czy możesz wyjaśnić w kilku słowach, jak działa powyższa wtyczka? Jestem trochę zdezorientowany, ponieważ jak wiem metoda __call jest wykonywana, jeśli spróbujemy wykonać metodę, która nie istnieje dla konkretnego obiektu. Wydaje się, że to prawda, ponieważ w app / code / Magento / Quote / Model / Quote / Address.php nie widzę takiej metody - tylko komentarz:

/** * Sales Quote address model ... * @method Address setShippingMethod(string $value)

  1. Dlaczego korzystasz z przechwytywania, gdy nie ma implementacji metody?
  2. Dalej widzę $subject->setInpostMachinei $subject->getCarrierOffice(null);Czy to oznacza, że ​​powyższa metoda wtyczki zostanie wykonana ponownie, ponieważ nie ma metody setInpostMachine () i getCarrierOffice () w klasie Adress? Dla mnie wygląda to na pętlę.
  3. Skąd wykonać Magento setShippingMethod()? Jak zwykle stosuje się tę metodę? Nie mogę znaleźć żadnych przechwyceń similar w kodzie Magento.
użytkownik2089098
źródło
Ok, więc przygotowałem odpowiedź na podstawie modułu, który napisałem do testów, użyłem pola inpost_machine, więc ten po prostu nie został poprawnie zmieniony na carrier_office w tym miejscu. Po drugie, podczas opracowywania tego modułu nie znalazłem miejsca, w którym mógłbym otrzymać zarówno wybranego operatora, jak i adres z atrybutami rozszerzenia wysłanymi oprócz setShippingMethodwywołania AddressInterfaceobiektu, a ponieważ nie ma takiej metody, musiałem użyć około__zadzwoń, aby sprawdzić, czy setShippingMethodzostał nazwany lub jakieś inne magiczne pole. W tej chwili znalazłem lepsze miejsce i opublikuję je w nowej odpowiedzi.
Zefiryn