0

I am trying to disable the default sorting based on price, that is happening on shipping methods.

I found that this is happening in sortRatesByPrice()

vendor/magento/module-shipping/Model/Rate/Result.php

public function sortRatesByPrice()
{
    if (!is_array($this->_rates) || !count($this->_rates)) {
        return $this;
    }
    /* @var $rate \Magento\Quote\Model\Quote\Address\RateResult\Method */
    foreach ($this->_rates as $i => $rate) {
        $tmp[$i] = $rate->getPrice();
    }

    natsort($tmp);

    foreach ($tmp as $i => $price) {
        $result[] = $this->_rates[$i];
    }

    $this->reset();
    $this->_rates = $result;
    return $this;
}

I basically just want to disable the sorting that happens here. (I.e. comment natsort($tmp))

I have tried to create a plugin for this, but this is not working.

This is my 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\Shipping\Model\Rate\Result">
        <plugin name="dm_shipping_sortshipping" type="DM\Shipping\Plugin\Rate\Result" sortOrder="1" disabled="false" />
    </type>
    
</config>

This is my plugin

<?php

    namespace DM\Shipping\Plugin\Rate;

    class Result {

        public function beforeSortRatesByPrice()
        {
            $writer = new \Laminas\Log\Writer\Stream(BP . '/var/log/dm_debug.log');
            $logger = new \Laminas\Log\Logger();
            $logger->addWriter($writer);
            $logger->info('beforeSortRatesByPrice');
        }

        public function aroundSortRatesByPrice()
        {
            $writer = new \Laminas\Log\Writer\Stream(BP . '/var/log/dm_debug.log');
            $logger = new \Laminas\Log\Logger();
            $logger->addWriter($writer);
            $logger->info('aroundSortRatesByPrice');
        }

        public function afterSortRatesByPrice()
        {
            $writer = new \Laminas\Log\Writer\Stream(BP . '/var/log/dm_debug.log');
            $logger = new \Laminas\Log\Logger();
            $logger->addWriter($writer);
            $logger->info('beforeSortRatesByPrice');
        }

    }

Why are none of these firing? Log is empty.

1
  • DId you ever get a working solution? As I'm having the same issues
    – Goose84
    Mar 4, 2022 at 10:31

2 Answers 2

0

If you are using an around plugin, you don't need the before and after plugins. As you can see in the magento dev docs (https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html), you are missing the methods arguments. Every plugin method must have at least the subject:

        public function beforeSortRatesByPrice(\Magento\Shipping\Model\Rate\Result $subject)
        {
            $writer = new \Laminas\Log\Writer\Stream(BP . '/var/log/dm_debug.log');
            $logger = new \Laminas\Log\Logger();
            $logger->addWriter($writer);
            $logger->info('beforeSortRatesByPrice');
        }

        public function aroundSortRatesByPrice(\Magento\Shipping\Model\Rate\Result $subject, callable $proceed)
        {
            $writer = new \Laminas\Log\Writer\Stream(BP . '/var/log/dm_debug.log');
            $logger = new \Laminas\Log\Logger();
            $logger->addWriter($writer);
            $logger->info('aroundSortRatesByPrice');
        }

        public function afterSortRatesByPrice(\Magento\Shipping\Model\Rate\Result $subject, $result)
        {
            $writer = new \Laminas\Log\Writer\Stream(BP . '/var/log/dm_debug.log');
            $logger = new \Laminas\Log\Logger();
            $logger->addWriter($writer);
            $logger->info('beforeSortRatesByPrice');
        }

Remember to clean generated code (rm -rf generated/*)

2
  • Still not working with your suggested fixes :(
    – puntable
    Dec 9, 2020 at 8:15
  • Can you check your exception log pls? Dec 9, 2020 at 10:27
0

The plugin for Magento\Shipping\Model\Rate\Result didn't work for me, because this sorting is called in Magento\Shipping\Model\Rate\CarrierResult::getAllRates() which calls with parent::sortRatesByPrice(); and i guess this way doesn't "use" the plugin preference.

So, instead i made a plugin for Magento\Shipping\Model\Rate\CarrierResult

<type name="Magento\Shipping\Model\Rate\CarrierResult">
    <plugin name="custom_shipping_sortshipping" type="Vendor\Shipping\Plugin\Rate\CarrierResult" sortOrder="1" disabled="false" />
</type>

Then in the Vendor\Shipping\Plugin\Rate\CarrierResult you can use the plugin features to create a before/around/after as needed. In my case i used the afterGetAllRates, for ex:

<?php

namespace Vendor\Shipping\Plugin\Rate;

class CarrierResult
{

    public function afterGetAllRates(\Magento\Shipping\Model\Rate\CarrierResult $subject, $result)
    {
        // Custom sort function on $result

        return $result;
    }

}

Maybe it's a bit late, but found this question when searching for a solution. And since i found one, it might help someone else.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.