Declaring Aggregates

The class-attribute form shown in the Overview is the canonical way to declare an aggregate. Two alternatives cover special cases.

Method-override form

For runtime-conditional aggregates (or large declaration sets that would clutter the class header), override nestedSetAggregates():

class Category extends Model implements HasNestedSet
{
    use NodeTrait;

    /** @return list<\Vusys\NestedSet\Aggregates\AggregateDefinition> */
    protected function nestedSetAggregates(): array
    {
        return [
            Aggregate::sum('articles')->into('articles_total'),
            Aggregate::count()->into('articles_count'),
            Aggregate::avg('articles')->into('articles_avg'),
        ];
    }
}

Attribute and method-override forms can coexist; attribute declarations come first, method override appends. Same precedence rule as scope resolution.

How AVG is computed

Aggregate::avg('articles') (and avg: on the attribute) is maintained as a derived value, not as a real AVG(...) UPDATE. The registry auto-promotes companion SUM and COUNT definitions over the same source column unless you've already declared them explicitly with matching filters. The AVG display column is then written as sum / NULLIF(count, 0) after every delta — so the ancestor UPDATE stays one statement and the column returns NULL for empty subtrees rather than dividing by zero.

The auto-promoted companions follow the {avg_column}__sum / {avg_column}__count naming convention; both must exist in the migration alongside the AVG column. $model->getAggregateDefinitions() filters internal companions out of its return list. If you already declared a SUM(source) or COUNT(source) aggregate with the same filter as the AVG, the registry reuses your user-facing column instead of promoting a hidden one. See Listener AVG for the listener-side equivalent.

Introspection

For tooling that needs to enumerate what a model declares at runtime — Filament resources, admin generators, export scripts — use $model->getAggregateDefinitions(), which returns the user-facing AggregateDefinition list (internal AVG companions are filtered out).