Drupal commerce provides several standard shipping methods that we can package according to different criteria (order amount, customer profile, order type, order weight, product type, etc.). For specific needs, we can add a customised shipping method which can then perform the necessary calculations to determine the delivery cost.

To do this, simply create a Commerce Plugin of type CommerceShippingMethod provided by the Commerce shipping module. Let’s take an example, by creating a new shipping method that will calculate the cost of shipping based on the weight of the order.

Let’s create the RateParWeight.php file and place it in a custom module My Module in the src/Plugin/Commerce/ShippingMethod directory.

namespace Drupal\my_module\Plugin\Commerce\ShippingMethod;

use Drupal\commerce_price\Price;
use Drupal\commerce_shipping\Entity\ShipmentInterface;
use Drupal\commerce_shipping\PackageTypeManagerInterface;
use Drupal\commerce_shipping\Plugin\Commerce\ShippingMethod\ShippingMethodBase;
use Drupal\commerce_shipping\ShippingRate;
use Drupal\commerce_shipping\ShippingService;
use Drupal\physical\Weight;
use Drupal\physical\WeightUnit;
use Drupal\state_machine\WorkflowManagerInterface;

 * Provides the Rate per weight shipping method.
 * @CommerceShippingMethod(
 *   id = "rate_per_weight",
 *   label = @Translation("Rate per weight"),
 * )
class RatePerWeight extends ShippingMethodBase {

  private $rounder;

   * Constructs a new FlatRate object.
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\commerce_shipping\PackageTypeManagerInterface $package_type_manager
   *   The package type manager.
   * @param \Drupal\state_machine\WorkflowManagerInterface $workflow_manager
   *   The workflow manager.
  public function __construct(array $configuration, $plugin_id, $plugin_definition, PackageTypeManagerInterface $package_type_manager, WorkflowManagerInterface $workflow_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $package_type_manager, $workflow_manager);
    $this->services['default'] = new ShippingService('default', $this->t('Home delivery'));
    $this->rounder = \Drupal::service('commerce_price.rounder');

   * {@inheritdoc}
  public function calculateRates(ShipmentInterface $shipment) {
    // Index 0 is for Weight 0 to 5kg.
    // Index 1 is for Weight 5 to 10kg.
    // Index 2 is for Weight over 10kg.
    $amounts = [10, 20, 30];

    // Default value is for shipping where weight is superior to 10kg.
    $weight_rate = 2;
    $total_weight = $shipment->getWeight();
    if (!$total_weight) {
      $total_weight = new Weight('0', WeightUnit::KILOGRAM);
    $total_weight = $total_weight->convert(WeightUnit::KILOGRAM);
    $five_kg_weight = new Weight('5', WeightUnit::KILOGRAM);
    $ten_kg_weight = new Weight('10', WeightUnit::KILOGRAM);
    if ($total_weight->lessThan($five_kg_weight)) {
      $weight_rate = 0;
    elseif ($total_weight->greaterThanOrEqual($five_kg_weight) &&
      $total_weight->lessThan($ten_kg_weight)) {
      $weight_rate = 1;
    $shipping_amount = $amounts[$weight_rate];
    $amount = new Price((string) $shipping_amount, $shipment->getOrder()->getTotalPrice()->getCurrencyCode());
    $amount = $this->rounder->round($amount);

    $rates = [];
    $rates[] = new ShippingRate([
      'shipping_method_id' => $this->parentEntity->id(),
      'service' => $this->services['default'],
      'amount' => $amount,
    return $rates;


This basic shipping method will then calculate the delivery amount according to the table ($amounts) provided as a hard parameter in the plugin. This example allows you to select this shipping plugin when creating a delivery method available in the checkout.


Sélection du plugin rate per weight


Note that it would be possible to use the standard shipping methods provided by Commerce Shipping, and to package each shipping method according to the weight of the order. This type of bespoke delivery method may be simpler to maintain, or may involve more complex logic in determining the delivery cost for an order.



Source link