setono / sylius-tier-pricing-plugin
Use price tiers in your Sylius store.
Package info
github.com/Setono/sylius-tier-pricing-plugin
Type:sylius-plugin
pkg:composer/setono/sylius-tier-pricing-plugin
Fund package maintenance!
Requires
- php: >=8.2
- brick/math: ^0.12.0 || ^0.13.0
- doctrine/collections: ^2.2
- doctrine/orm: ^3.6
- sylius/admin-bundle: ^2.0
- sylius/channel: ^2.0
- sylius/channel-bundle: ^2.0
- sylius/core: ^2.0
- sylius/core-bundle: ^2.0
- sylius/order: ^2.0
- sylius/product: ^2.0
- sylius/product-bundle: ^2.0
- sylius/resource-bundle: ^1.11
- symfony/config: ^6.4 || ^7.4
- symfony/dependency-injection: ^6.4 || ^7.4
- symfony/form: ^6.4 || ^7.4
- symfony/options-resolver: ^6.4 || ^7.4
- symfony/translation-contracts: ^2.5 || ^3.4
- symfony/ux-autocomplete: ^2.35
- symfony/ux-live-component: ^2.35
- symfony/validator: ^6.4 || ^7.4
- webmozart/assert: ^1.11
Requires (Dev)
- api-platform/symfony: ^4.3.3
- matthiasnoback/symfony-dependency-injection-test: ^6.3
- payum/core: ^1.7.5
- setono/sylius-plugin: ^2.0
- sylius/grid-bundle: ^1.15
- sylius/sylius: ~2.2.5
- symfony/debug-bundle: ^6.4 || ^7.4
- symfony/dotenv: ^6.4 || ^7.4
- symfony/intl: ^6.4 || ^7.4
- symfony/property-info: ^6.4 || ^7.4
- symfony/serializer: ^6.4 || ^7.4
- symfony/web-profiler-bundle: ^6.4 || ^7.4
- symfony/webpack-encore-bundle: ^2.2
This package is auto-updated.
Last update: 2026-05-11 09:33:31 UTC
README
Use quantity-based price tiers in your Sylius store. Set a tier like "10% off when buying 5 or more" on a product, optionally scoped to a specific channel and/or variant; the discount is applied automatically as a per-unit ORDER_UNIT_PROMOTION_ADJUSTMENT with originCode = 'tier_pricing'.
Requirements
- PHP
>=8.2 - Symfony
^6.4 || ^7.4 - Sylius
^2.0
For Sylius 1.x see the 1.x branch. Upgrading from 1.x → 2.x? See UPGRADE.md.
Installation
composer require setono/sylius-tier-pricing-plugin
Register the bundle in config/bundles.php:
return [ // ... Setono\SyliusTierPricingPlugin\SetonoSyliusTierPricingPlugin::class => ['all' => true], ];
Make your App\Entity\Product use the plugin's trait + interface:
use Setono\SyliusTierPricingPlugin\Model\ProductInterface as TierPricingProductInterface; use Setono\SyliusTierPricingPlugin\Model\ProductTrait as TierPricingProductTrait; class Product extends BaseProduct implements TierPricingProductInterface { use TierPricingProductTrait { TierPricingProductTrait::__construct as private _initializePriceTiers; } public function __construct() { parent::__construct(); $this->_initializePriceTiers(); } }
Wire the resource override in config/packages/_sylius.yaml:
sylius_product: resources: product: classes: model: App\Entity\Product
Update the database schema:
bin/console doctrine:migrations:diff bin/console doctrine:migrations:migrate
How it works
After install, products in the admin get a Price tiers tab (rendered via Twig hooks into the product update/create page). Each tier has:
- Quantity — minimum units the customer must add to the cart for the tier to kick in.
- Discount — percentage off, kept as a numeric string and computed with
brick/mathto avoid float drift. - Channel — optional; restricts the tier to one channel.
- Variant — optional; restricts the tier to one variant of the product.
When an order is processed, the PriceTiersOrderProcessor (priority 15, runs before tax/shipping) picks the best-matching tier per item using the precedence (channel + variant) > variant > channel > generic, computes the discount with RoundingMode::CEILING, distributes it across units via sylius.distributor.integer, and attaches one adjustment per unit.