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;
}
}
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: