Calculated property
| public function calculateAge(): ?float
{
// calculation of age (today - month of manufacture)
$manufacturemonth = $this->getProperty('manufacture_month'); // DateProperty object
$manufacturemonth_year_month = $manufacturemonth->getValue(); // "2026-01"
if (!$manufacturemonth_year_month)
return null;
$temp = new DateTime($manufacturemonth_year_month); // DateTime object. Let's take the 1st or that month.
$today = new \Datetime(); // DateTime object / today by default
$diff = $today->diff($temp); // calculate the difference between manu-date and today
// for leasing contracts we usually calculate months like 48.
return $diff->y * 12 + $diff->m; // let's forget about the days. We don't even know exact manuf-date, only month.
}
|
Now, in getAdditionalProperties() we can create a new property which automatically calculates its' value:
| (new NumericPropertyCalculated('age', fn() => $this->calculateAge()))
->label("Vehicle age in months"),
|
This is the complete getAdditionalProperties() function
| protected function getAdditionalProperties(): array
{
return [
(new StringProperty("licenseplate"))->required(),
(new StringProperty("chassisnumber"))->required(),
// simple lookup list for now (array or models)
(new SelectProperty("model", [
'Audi A4',
'Audi A6',
'Audi A8',
]))->required(),
(new MonthProperty("manufacture_month")),
(new NumericPropertyCalculated('age', fn() => $this->calculateAge()))->label("Vehicle age in months"),
(new MonthProperty("purchase_month")),
(new NumericWithUnitProperty("purchase_mileage", ['km', 'ml'], 'km', 1, false)),
];
}
|
Save the file and reload your page:

We care for layout later. For the moment, let us concentrate on the model.
Now that we have a calculated age field, we can use the result in list view label. We can evaluate the age-property for each Vehicle object.
| /**
* @var NumericPropertyCalculated
*/
$age = $this->getProperty('age');
$age_value = $age ? $age->calculate($this) : null;
|
This is the complete function:
| public function getLabelHtml(): string
{
$diff_months = $this->calculateAge();
// gather our data
$model = $this->getProperty('model');
$month = $this->getProperty('manufacture_month');
/**
* @var NumericPropertyCalculated
*/
$age = $this->getProperty('age');
$age_value = $age ? $age->calculate($this) : null;
$details = [
$model?->toDisplayValue(),
$month?->toDisplayValue(),
($age_value ? "{$age_value} months" : ''),
];
$details = array_filter($details);// remove empty entries
// create a tile
\System\UI\Output::use(); // important for autoloading
$tile = new \System\UI\Output\Elements\Tile('car', $this->licenseplate);
if ($details)
$tile->subtitle = implode(' • ', $details);
return $tile;
}
|
And still we see the calculated age in list view:
