How to add a custom cart promotion rule?
Adding custom promotion rules is a common need in real-world shops. For example, you might want to offer exclusive discounts to premium customers. To implement this, you'll create a new PromotionRule
that checks whether a customer qualifies.
1. Create a New Promotion Rule Checker
Define a custom RuleChecker
that determines rule eligibility:
<?php
namespace App\Promotion\Checker\Rule;
use Sylius\Component\Promotion\Checker\Rule\RuleCheckerInterface;
use Sylius\Component\Promotion\Model\PromotionSubjectInterface;
class PremiumCustomerRuleChecker implements RuleCheckerInterface
{
public const TYPE = 'premium_customer';
public function isEligible(PromotionSubjectInterface $subject, array $configuration): bool
{
return $subject->getCustomer()?->isPremium() === true;
}
}
Ensure the getCustomer()
method exists on your PromotionSubjectInterface
.
2. Add a Premium Field to the Customer Entity
First, extend the Customer
entity to include a premium
boolean field:
<?php
// App\Entity\Customer\Customer
declare(strict_types=1);
namespace App\Entity\Customer;
use Doctrine\ORM\Mapping as ORM;
use Sylius\Component\Core\Model\Customer as BaseCustomer;
#[ORM\Entity]
#[ORM\Table(name: 'sylius_customer')]
class Customer extends BaseCustomer
{
#[ORM\Column(type: 'boolean', options: ['default' => false])]
private bool $premium = false;
public function isPremium(): bool
{
return $this->premium;
}
public function setPremium(bool $premium): void
{
$this->premium = $premium;
}
}
Apply the Doctrine migration:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
3. Extend the Customer Admin Form
Now, extend the customer form to allow editing the premium field in the Sylius admin:
<?php
// src/Form/Extension/CustomerTypeExtension.php
namespace App\Form\Extension;
use Sylius\Bundle\AdminBundle\Form\Type\CustomerType;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
final class CustomerTypeExtension extends AbstractTypeExtension
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('premium', CheckboxType::class, [
'label' => 'Premium',
'required' => false,
]);
}
public static function getExtendedTypes(): iterable
{
return [CustomerType::class];
}
}
If your autowiring is disabled, you will need also to register your CustomerTypeExtension
in config/services.yaml
:
services:
App\Form\Extension\CustomerTypeExtension:
tags:
- { name: form.type_extension }
4. Create the Template Section for the Premium Field
Inspect the admin customer form to find the appropriate hook. The relevant section is sylius_admin.customer.update.content.form.sections.general
.

Create a new Twig template for this field:
{# templates/admin/customer/form/sections/general/premium.html.twig #}
{{ form_row(hookable_metadata.context.form.premium) }}
Then configure the hook in your sylius.yaml
:
# config/packages/_sylius.yaml
sylius_twig_hooks:
hooks:
'sylius_admin.customer.update.content.form.sections.general':
premium:
template: '/admin/customer/form/sections/general/premium.html.twig'
priority: -50
Learn more about twig hooks here!
5. Create a Configuration Form Type (Optional)
Even if no configuration is needed, Sylius expects a form type to exist for every rule.
<?php
// src/Form/Type/Rule/PremiumCustomerConfigurationType.php
namespace App\Form\Type\Rule;
use Symfony\Component\Form\AbstractType;
class PremiumCustomerConfigurationType extends AbstractType
{
public function getBlockPrefix(): string
{
return 'app_promotion_rule_premium_customer_configuration';
}
}
If your autowiring is disabled, you will need also to register your PremiumCustomerConfigurationType
in config/services.yaml
:
services:
App\Form\Type\Rule\PremiumCustomerConfigurationType:
tags:
- { name: form.type }
6. Register Services
Add both the rule checker and form type to your config/services.yaml
:
# config/services.yaml
services:
App\Promotion\Checker\Rule\PremiumCustomerRuleChecker:
tags:
- {
name: sylius.promotion_rule_checker,
type: premium_customer,
form_type: App\Form\Type\Rule\PremiumCustomerConfigurationType,
label: 'Premium customer'
}
✅ Result
You can now select the Premium customer rule type when creating or editing a cart promotion in the Sylius Admin panel.

To make this rule applicable, edit a customer and mark them as premium.

Promotions using this rule will now apply (or not) based on whether the customer is marked as premium— regardless of whether a coupon is used:

If your rule requires configuration fields (like thresholds or limits), see how it’s handled in ItemTotalConfigurationType
.
Last updated
Was this helpful?