floflax.io
Jean Marc
Installation costs
Installation is free if the customer orders at least 60 days before the event.
floflax.io
Installation costs
Installation is free if the customer orders at least 60 days before the event.
final class EarlyBirdInstallationFeeChecker
{
public function isFree(Order $order): bool
{
$deadline = ($order->getEvent()->getStartDate())
->modify('-60 days');
return $order->getCreatedAt() <= $deadline;
}
}floflax.io
Installation costs v2
Installation is free if the exhibitor has exhibited 3 or more consecutive years, or if their booth surface exceeds 50m².
Installation costs
Installation is free if the customer orders at least 60 days before the event.
floflax.io
Installation costs v2
Installation is free if the exhibitor has exhibited 3 or more consecutive years, or if their booth surface exceeds 50m².
Installation costs
Installation is free if the customer orders at least 60 days before the event.
floflax.io
final class LoyaltyInstallationFeeChecker
{
public function isFree(Order $order): bool
{
$customer = $order->getCustomer();
return $this->getConsecutiveYears($customer) >= 3
|| $order->getBooth()->getSurface() > 50;
}
private function getConsecutiveYears(
Customer $customer
): int {
// ...
}
}Installation costs v3
Installation is free if the exhibitor has exhibited 2 or more consecutive years and the exhibitor is a sponsor of the event.
Installation costs
Installation is free if the customer orders at least 60 days before the event.
Installation costs v2
Installation is free if the exhibitor has exhibited 3 or more consecutive years, or if their booth surface exceeds 50m².
floflax.io
floflax.io
formula 🔮
floflax.io
floflax.io
my-website.comformula 🔮
floflax.io
floflax.io
floflax.io
floflax.io
$services->set(IndexBuilder::class)
->arg(
'$indexName',
expr("env('index_prefix') ~ '_' ~ parameter('main_index_name')"),
);floflax.io
use Symfony\Component\Security\Http\Attribute\IsGranted;
final class ViewPostController
{
#[IsGranted('"ROLE_ADMIN" in roles or is_granted("VIEW", subject)', subject: 'post')]
public function __invoke(Post $post): Response
{
return new Response('ok');
}
}floflax.io
floflax.io
$el = new ExpressionLanguage();
$isAGreatCustomer = $el->evaluate(
'((100 * order.discount) / order.total) < 5',
['order' => $customer->getLastOrder()]),
);floflax.io
$customer->orders ->filter(/* placed in 2025 */) ->count() > 0 && $loyaltyProgram->customers ->contains($customer) && $customer->billingAddress ->country() === 'France';
The customer placed an order in 2025, and he is registered to the loyalty program and his billing address is located in France
floflax.io
$el = new ExpressionLanguage();
$ruleToBeEligible = <<<EOT
placed_an_order_in(customer, 2025)
&&
is_registered_to_the_loyalty_program(customer)
&&
billing_address_located_in(customer, "France")
EOT;
$eligible = $el->evaluate(
$ruleToBeEligible,
['customer' => $customer],
);The customer placed an order in 2025, and he is registered to the loyalty program and his billing address is located in France
floflax.io
$el = new ExpressionLanguage();
$eligible = $el->evaluate(
$rules->findEligibleForDiscount(),
['customer' => $customer],
);The customer placed an order in 2025, and he is registered to the loyalty program and his billing address is located in France
floflax.io
$el = new ExpressionLanguage();
$eligible = $el->evaluate(
$rules->findEligibleForDiscount(),
['customer' => $customer],
);floflax.io
The customer placed an order in 2025, and he is registered to the loyalty program and his billing address is located in France
floflax.io
Symfony is a great framework
floflax.io
Symfony is a great framework
VERB
NOUN
ADJ
NOUN
DET
floflax.io
NOUN PHRASE
Symfony is a great framework
VERB
NOUN
ADJ
NOUN
DET
VERB
NOUN
floflax.io
VERBAL PHRASE
NOUN PHRASE
Symfony is a great framework
VERB
NOUN
ADJ
NOUN
DET
VERB
NOUN
NOUN
floflax.io
PHRASE
VERBAL PHRASE
NOUN PHRASE
Symfony is a great framework
VERB
NOUN
ADJ
NOUN
DET
VERB
NOUN
NOUN
floflax.io
P
N
VP
V
NP
D
A
N
PHRASE
VERBAL PHRASE
NOUN PHRASE
Symfony is a great framework
VERB
NOUN
ADJ
NOUN
DET
VERB
NOUN
NOUN
floflax.io
(boost + ratings.average) / 2
floflax.io
(boost + ratings.average) / 2
VAR.
OP.
(
VAR.
)
OP.
CST.
.
CST.
floflax.io
VAR.
OP.
(
PROPERTY ACCESSOR
)
OP.
CST.
(boost + ratings.average) / 2
VAR.
OP.
(
VAR.
)
OP.
CST.
.
CST.
floflax.io
ADDITION OPERATOR
OP.
CST.
VAR.
OP.
(
PROPERTY ACCESSOR
)
OP.
CST.
(boost + ratings.average) / 2
VAR.
OP.
(
VAR.
)
OP.
CST.
.
CST.
floflax.io
DIVISION OPERATOR
ADDITION OPERATOR
OP.
CST.
VAR.
OP.
(
PROPERTY ACCESSOR
)
OP.
CST.
(boost + ratings.average) / 2
VAR.
OP.
(
VAR.
)
OP.
CST.
.
CST.
floflax.io
/
+
C
V
P
V
C
DIVISION OPERATOR
ADDITION OPERATOR
OP.
CST.
VAR.
OP.
(
PROPERTY ACCESSOR
)
OP.
CST.
(boost + ratings.average) / 2
VAR.
OP.
(
VAR.
)
OP.
CST.
.
CST.
floflax.io
foo === bar.baz
// String
floflax.io
foo === bar.baz
f
o
o
=
=
=
b
a
r
.
b
a
z
// Character stream
_
_
// String
floflax.io
foo === bar.baz
f
o
o
=
=
=
b
a
r
.
b
a
z
foo
===
bar
.
baz
// Tokens
VAR.
OP.
VAR.
.
CST.
// Character stream
// String
floflax.io
foo
===
bar
.
baz
PROPERTY ACCESSOR
VAR.
OP.
VAR.
CST.
.
VAR.
OP.
IDENTICAL OPERATOR
===
V
P
V
C
// Tokens
floflax.io
===
V
P
V
C
// Syntax tree
// Magic
floflax.io
floflax.io
foo === bar.baz
breaks into tokens
builds the syntax tree
walks the tree for a result
customer in loyaltyProgram.registered
floflax.io
🗣️ Language
🧩 Exposing objects
specific syntax
in
internal structure
.registered
is_registred_to_the_loyalty_program(customer)
$loyaltyProgram->registered->contains($customer)floflax.io
🗣️ Language
new ExpressionFunction(
name: 'is_registred_to_the_loyalty_program',
compiler: static function (string $s): string {
// ...
},
evaluator: static function (array $args, Customer $c): bool {
return $args['loyaltyProgram']->registred->contains($c);
},
)floflax.io
🗣️ Language
final class LoyaltyProgramFunctionProvider implements ExpressionFunctionProviderInterface
{
public function getFunctions(): array
{
return [
new ExpressionFunction('is_registred_to_the_loyalty_program', ...),
new ExpressionFunction(...),
// ...
];
}
}floflax.io
🗣️ Language
use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseEL;
final class ECommerceExpressionLanguage extends BaseEL
{
public function __construct(
CacheItemPoolInterface $cache = null,
array $providers = [],
) {
array_unshift($providers, new LoyaltyProgramFunctionProvider());
array_unshift($providers, new CouponsFunctionProvider());
parent::__construct($cache, $providers);
}
}floflax.io
🗣️ Language
final class EligibilityChecker
{
public function __construct(
private ECommerceExpressionLanguage $el,
) {}
public function isEligible(string $condition, Customer $customer): bool
{
return $this->el->evaluate($condition, [
'customer' => $customer,
]);
}
}floflax.io
placed_an_order_in(customer, 2025)
&& is_registered_to_the_loyalty_program(customer)
&& billing_address_located_in(customer, "France")'🗣️ Language
floflax.io
🧩 Exposing objects
final class EligibilityChecker
{
public function __construct(
private ECommerceExpressionLanguage $el,
private NormalizerInterface $normalizer,
) {}
public function isEligible(string $condition, Customer $customer): bool
{
return $this->el->evaluate($condition, [
'customer' => $this->normalizer->normalize($customer),
]);
}
}floflax.io
https://jsfiddle.net/FloFlax/8fukw2yo/latest/final class UpdateIsEligibleForDiscountRuleAction extends AbstractController
{
public function __invoke(Request $request, RuleRepository $rules): Response
{
$expression = $rules->getEligibleForDiscount();
$form = $this->createForm(ExpressionType::class, $expression);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$rules->saveEligibleForDiscount($form->getData());
return $this->redirectToRoute('rules');
}
return $this->render('update_is_eligible_for_discount_rule.html.twig', [
'form' => $form,
]);
}
}floflax.io
$el->lint($expression);floflax.io
class ExpressionLanguage
{
/**
* Validates the syntax of an expression.
*
* @param array $names The list of acceptable variable names in the expression
* @param int-mask-of<Parser::IGNORE_*> $flags
*
* @throws SyntaxError When the passed expression is invalid
*/
public function lint(Expression|string $expression, array $names, int $flags = 0): void
}['order', 'customer']
readonly final class ApplyDiscountCommandHandler
{
public function __construct(
private ECommerceExpressionLanguage $el,
private RuleRepository $rules,
private LoyaltyProgram $loyaltyProgram,
) {
}
public function __invoke(ApplyDiscountCommand $command): void
{
$eligible = $el->evaluate($rules->findEligibleForDiscount(), [
'customer' => $command->customer,
'loyaltyProgram' => $this->loyaltyProgram,
]);
if (!$eligible) {
return;
}
// ...
}
}floflax.io
floflax.io
$el->lint($expression);$cache = new RedisAdapter(...);
$expressionLanguage = new ExpressionLanguage($cache);is_registered_to_the_loyalty_program(customer) or is_sponsor(customer)total / items.countdividing by 0 ?
floflax.io