Skip to main content

Stop Writing Calculator Classes for Simple Operations in Pimcore

Luke MacAusland  |  December 12, 2025  |  Reading Time: mins

The Problem Every Pimcore Developer Faces

You need a calculated field that displays a product SKU in uppercase. Simple, right?

Until now, you had to write this:

<?php
namespace App\Calculator;

use Pimcore\Model\DataObject\Concrete;
use Pimcore\Model\DataObject\ClassDefinition\CalculatorClassInterface;
use Pimcore\Model\DataObject\Data\CalculatedValue;

class UppercaseSkuCalculator implements CalculatorClassInterface
{
    public function compute(Concrete $object, CalculatedValue $context): string
    {
        return strtoupper($object->getSku());
    }

    public function getCalculatedValueForEditMode(
        Concrete $object,
        CalculatedValue $context
    ): string {
        return $this->compute($object, $context);
    }
}
 

25 lines of code for strtoupper().

Need to trim whitespace? Another calculator class. Format a date? Another class. Convert to lowercase? You get the idea.

The Solution: Expression Functions (Now in Pimcore Core)

We've contributed a feature to Pimcore that lets you register expression functions once and use them everywhere. No more calculator classes for simple operations.

Live Code: See the actual implementation in:

How It Works

1. Register Functions Once

Create a provider with the functions you need:

<?php
namespace App\ExpressionLanguage;

use Symfony\Component\ExpressionLanguage\ExpressionFunction;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;

class BasicExpressionProvider implements ExpressionFunctionProviderInterface
{
    public function getFunctions(): array
    {
        return [
            new ExpressionFunction(
                "upper",
                function ($str) {
                    return sprintf("strtoupper(%s)", $str);
                },
                function ($variables, $value) {
                    return strtoupper($value);
                }
            ),

            new ExpressionFunction(
                "trim",
                function ($str) {
                    return sprintf("trim(%s)", $str);
                },
                function ($variables, $value) {
                    return trim($value);
                }
            ),
        ];
    }
}

2. Register as Service

services:
   App\ExpressionLanguage\BasicExpressionProvider:
       tags:
           - { name: 'pimcore.calculated_value.expression_language_provider' }

3. Use Everywhere

Now in ANY calculated field:

upper(object.getSku())
lower(object.getCode())
trim(object.getName())


Add Your Own Functions

Need more functions? Add them to your provider:

// SEO-friendly slug
new ExpressionFunction(
    'slug',
    function ($str) {
        return sprintf('preg_replace("/[^a-z0-9-]/", "-", strtolower(%s))', $str);
    },
    function ($variables, $value) {
        $slug = strtolower(trim($value));
        return preg_replace('/[^a-z0-9-]+/', '-', $slug);
    }
),

// Format price with currency
new ExpressionFunction(
    'price',
    function ($amount, $symbol = '$') {
        return sprintf('%s . number_format(%s, 2)', $symbol, $amount);
    },
    function ($variables, $amount, $symbol = '$') {
        return $symbol . number_format($amount, 2);
    }
),

// Date formatting
new ExpressionFunction(
    'format_date',
    function ($date, $format = '"Y-m-d"') {
        return sprintf('%s ? %s->format(%s) : ""', $date, $date, $format);
    },
    function ($variables, $date, $format = 'Y-m-d') {
        return $date ? $date->format($format) : '';
    }
),

When to Still Use Calculator Classes

Keep calculator classes for:

  • Complex business logic requiring multiple steps
  • Operations needing dependency injection
  • External API calls or database queries

Use expression functions for:

  • String transformations (upper, lower, trim, slug)
  • Number formatting (currency, percentage)
  • Date formatting
  • Any single-line transformation

Try It In Your Project

  1.    Copy the BasicExpressionProvider code above (or write your own functions)
  2.    Register it in your services.yaml with the tag: pimcore.calculated_value.expression_language_provider
  3.    Clear cache: php bin/console cache:clear
  4.    Start using the functions in your calculated fields!

That's it. No more calculator classes for simple operations.

This feature is available in Pimcore 2025.4 and later. See the official documentation for more details.

Other Posts

Case Studies

Ready to get started?

Talk to an expert