How to add a custom shipping calculator?
Use Case
1. Create the Calculator Class
<?php
// src/Shipping/Calculator/WeightBasedRateCalculator.php
namespace App\Shipping\Calculator;
use Sylius\Component\Core\Exception\MissingChannelConfigurationException;
use Sylius\Component\Shipping\Calculator\CalculatorInterface;
use Sylius\Component\Shipping\Model\ShipmentInterface;
use Webmozart\Assert\Assert;
final class WeightBasedRateCalculator implements CalculatorInterface
{
public function calculate(ShipmentInterface $subject, array $configuration): int
{
Assert::isInstanceOf($subject, \Sylius\Component\Core\Model\ShipmentInterface::class);
$channelCode = $subject->getOrder()->getChannel()->getCode();
if (!isset($configuration[$channelCode])) {
throw new MissingChannelConfigurationException(sprintf(
'Channel %s has no amount defined for shipping method %s',
$subject->getOrder()->getChannel()->getName(),
$subject->getMethod()->getName(),
));
}
$rate = (int) $configuration[$channelCode]['amount'];
$totalWeight = array_sum(array_map(
fn($unit) => $unit->getShippable()->getWeight(),
iterator_to_array($subject->getUnits())
));
return $rate * $totalWeight;
}
public function getType(): string
{
return 'weight_based_rate';
}
}2. Register the Calculator as a Service
3. Create the Configuration Form Type
4. Register the Form Type
5. Add translations
Example Setup



Last updated
Was this helpful?
