Création d'une méthode de livraison

1. Fichier de configuration

Nous allons créer un mode de livraison à vélo, que nous appelerons bike. Dans le fichier config.xml de notre module, ajoutons la configuration de notre méthode de livraison :

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <carriers>
            <bike>
                <active>1</active>
                <sallowspecific>0</sallowspecific>
                <model>Adexos\Formation\Model\Carrier\Bike</model>
                <name>Bike</name>
                <price>10.00</price>
                <title>Delivery by bike</title>
            </newshipping>
        </carriers>
    </default>
</config>

Cette configuration par défaut correspond à de la configuration en admin, nous allons la déclarer dans le fichier etc/adminhtml/system.xml :

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
     <section id="carriers">
         <group id="bike" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
             <label>Delivery by bike</label>
             <field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0">
                 <label>Enabled</label>
                 <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
             </field>
            <field id="title" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
                  <label>Title</label>
              </field>
             <field id="name" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1">
                 <label>Method Name</label>
             </field>
             <field id="price" translate="label" type="text" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="0">
                 <label>Price</label>
                 <validate>validate-number validate-zero-or-greater</validate>
             </field>
             <field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0">
                 <label>Sort Order</label>
             </field>
             <field id="sallowspecific" translate="label" type="select" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="0">
                 <label>Ship to Applicable Countries</label>
                 <frontend_class>shipping-applicable-country</frontend_class>
                 <source_model>Magento\Shipping\Model\Config\Source\Allspecificcountries</source_model>
             </field>
             <field id="specificcountry" translate="label" type="multiselect" sortOrder="91" showInDefault="1" showInWebsite="1" showInStore="0">
                 <label>Ship to Specific Countries</label>
                 <source_model>Magento\Directory\Model\Config\Source\Country</source_model>
                 <can_be_empty>1</can_be_empty>
             </field>
             <field id="showmethod" translate="label" type="select" sortOrder="92" showInDefault="1" showInWebsite="1" showInStore="0">
                 <label>Show Method if Not Applicable</label>
                 <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
             </field>
             <field id="specificerrmsg" translate="label" type="textarea" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="1">
                 <label>Displayed Error Message</label>
             </field>
         </group>
     </section>
</system>
</config>

Créons ensuite le modèle correspondant à cette méthode de livraison. La classe sera celle que nous avons déclarée dans notre configuration, à savoir Adexos\Formation\Model\Carrier\Bike.

<?php
namespace Adexos\Formation\Model\Carrier;

use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Shipping\Model\Rate\Result;

class Bike extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements
\Magento\Shipping\Model\Carrier\CarrierInterface
{
    /**
    * @var string
    */
    protected $_code = 'bike';

    /**
    * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
    * @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
    * @param \Psr\Log\LoggerInterface $logger
    * @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory
    * @param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
    * @param array $data
    */
    public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
         \Psr\Log\LoggerInterface $logger,
         \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
         \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
         array $data = []
    ) {
         $this->_rateResultFactory = $rateResultFactory;
         $this->_rateMethodFactory = $rateMethodFactory;
         parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
    }

    /**
    * @return array
    */
    public function getAllowedMethods()
    {
         return ['bike' => $this->getConfigData('name')];
    }

    /**
    * @param RateRequest $request
    * @return bool|Result
    */
    public function collectRates(RateRequest $request)
    {
        if (!$this->getConfigFlag('active')) {
            return false;
        }
        /** @var \Magento\Shipping\Model\Rate\Result $result */
        $result = $this->_rateResultFactory->create();
        /** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
        $method = $this->_rateMethodFactory->create();
        $method->setCarrier('bike');
        $method->setCarrierTitle($this->getConfigData('title'));
        $method->setMethod('bike');
        $method->setMethodTitle($this->getConfigData('name'));
        /*you can fetch shipping price from different sources over some APIs, we used price from config.xml - xml node price*/
        $amount = $this->getConfigData('price');
        $method->setPrice($amount);
        $method->setCost($amount);
        $result->append($method);

        return $result;
    }
}