iosystems/shipping-bundle

This package is abandoned and no longer maintained. No replacement package was suggested.

Symfony 2 bundle for easly handling shipping costs.

dev-master 2014-05-14 06:42 UTC

This package is not auto-updated.

Last update: 2018-12-29 17:09:47 UTC


README

Symfony 2 bundle for easly handling shipping costs. This bundle is not tied in any way to external concept, class or interface (cart, shipping method, product, ...) and it's easly customizable.

Installation

Add iosystems/shipping-bundle in your composer.json:

{
    "require": {
        "iosystems/shipping-bundle": "dev-master"
    }
}

Enable the bundle in the kernel:

<?php
// app/AppKernel.php

public function registerBundles()
{
    $bundles = array(
        // ...
        new iOSystems\ShippingBundle\iOSystemsShippingBundle(),
    );
}

Finally update your vendors using composer update.

Configuration

In order to work properly you have to configure at least one built-in weght calculator and exactly one price calculator.

Weight calculators

This bundle utilizes the concept of weight calculators, that is services used to compute the weight for a single weightable instance.

Built-in calculators are:

Built-int weight calculators are disabled by default. Enable them using ~ or true or enabled: true (as long as there are no mandatory parameters), disable them using false or enabled: false:

# iOSystemsShippingBundle Configuration
iosystems_shipping:
	weight_calculators:
		gross: ~
		dimensional:
			divider: 5000
	# ...

You can easly add custom calculators.

Weight calculation strategy (how weight calculators are used)

Bundle weight calculation strategy is based on the max weight among supported weight calculators. For example, if $item is an instance of either GrossWeightableInterface and DimensionalWeightable, then the max between gross weight and dimentional weight is chosen. Total weight is just the sum of the above.

Weight calculation strategy can be replaced.

Price calculator

To compute the shipping price for a single weightable (or a list of weightables), the bundles uses a price calculator. A price calculator is an instance of PriceCalculatorInterface and it's used to compute the total price for a list of weightables.

fixed_amount

Calculates the shipping costs of weightables based on a constant amount (fixed price):

# iOSystemsShippingBundle Configuration
iosystems_shipping:
	# ...
	price_calculator:
		type: fixed_amount
		amount: 9.99

per_product

Calculates the shipping costs of weightables based on a single price field (uses Symfony PropertyAccess component internally):

# iOSystemsShippingBundle Configuration
iosystems_shipping:
	# ...
	price_calculator:
		type: per_product
		shipping_price_field: shipping_price

weight_treshold

Calculates the shipping costs of weightables based on weight/price thresholds. Thresholds come from providers but actually only Doctrine ORM is supported:

# iOSystemsShippingBundle Configuration
iosystems_shipping:
	# ...
	price_calculator:
		type: weight_treshold
		provider: orm
		entity_class: Acme\DemoBundle\Entity\WeightPriceTreshold

Your entity_class must be a Doctrine entity extending WeightTresholdInterface. Alternatively you can extend WeightTreshold, an abstract mapped superclass provinding the weight and price mappings.

For example, given the tresholds:

  • (A) up to weight 5 price is 4.99
  • (B) up to weight 10 price is 9.99
  • (C) up to weight 15 price is 14.99
  • (D) up to weight 20 price is 19.99

Then:

  • If total weight is 2.125 the price is 4.99 (A)
  • If total weight is 9.750 the price is 9.99 (B)
  • If total weight is 11.250 the price is 14.99 (B)
  • If total weight is 25.125 the price is 19.99 (D)

Usage

Depending on the configuration section for weight_calculators, implement the GrossWeightableInterface and/or DimensionalWeightableInterface:

<?php
// ...

use iOSystems\ShippingBundle\Weightable\GrossWeightableInterface;

class OrderDetail implements GrossWeightableInterface
{
	//...

	/**
	 * {@inheritdoc}
     */
	public function getQuantity()
    {
		return $this->quantity;
	}

	/**
	 * {@inheritdoc}
     */
	public function getWeigth()
    {
		return $this->weight;
	}
}

Then get the iosystems_shipping.manager service to calculate the weight/price of a single (or array of) weightables:

// Controller code
/** @var \iOSystems\ShippingBundle\Manager\ShippingManagerInterface $sm */
$sm = $this->get('iosystems_shipping.manager');

// Calculate the total price of a single weightable or array of weightables
$sm->getPrice($orderDetails);
$sm->getPrice($order->getDetails());

Customization

Adding weight calculators using Symfony 2 container tags

Weight calculators declare which type of weightable they support. In order to create a custom calculator, implement the WeightCalculatorInterface interface, provinding both supports() and getWeight() methods:

<?php
// ...

class MyWeightCalculator implements WeightCalculatorInterface
{
    /**
     * {@inheritdoc}
     */
    public function getWeight(WeightableInterface $weightable)
    {
		/** @var MyWeightableInterface $weightable */
		// Use your custom logic and return weight for a single weightable
		// ...
    }

	/**
	 * {@inheritdoc}
     */
	public function supports(WeightableInterface $weightable)
    {
		return $weightable instanceof MyWeightableInterface;
	}
}

Custom calculators are automatically added to the default calculation strategy (or any custom strategy extending the abstract class AbstractWeightCalculationStrategy) when using the iosystems_shipping.weight_calculator tag.

Contributing, TODO and ideas

Feel free to contribute to this project:

  • Lower the requirements for Symfony (actually >=2.3)
  • Specify how to change the default weight calculation strategy
  • Configuration and extension class refactoring
  • Remove uneeded services and parameters (depending on configuration)
  • Make use of custom mapping pass or DoctrineOrmMappingsPass based on Symfony version
  • Add new tresholds providers (from file, from configuration, etc.)
  • Add new price calculators (inversed thresholds, based on quantity, etc.)
  • Rewrite comments and this README in a better english :)