An Aggregate is a regular object, which contains state and methods to alter that state. It can be described as Entity, which carry set of behaviours. When creating the Aggregate object, you are creating the Aggregate Root.
#[Aggregate] // 1
#[AggregateIdentifier] // 2
private string $productId;
private string $name;
private integer $priceAmount;
private function __construct(string $orderId, string $name, int $priceAmount)
$this->productId = $orderId;
$this->name = $name;
$this->priceAmount = $priceAmount;
public static function register(RegisterProductCommand $command) : self
return new self(
#[CommandHandler] // 4
public function changePrice(ChangePriceCommand $command) : void
$this->priceAmount = $command->getPriceAmount();
Aggregatetells Ecotone, that this class should be registered as Aggregate Root.
AggregateIdentifieris the external reference point Aggregate.This field tells Ecotone to which Aggregate a given Command is targeted. You may also you expose identifier over public method by annotating it with attribute#[AggregateIdentifierMethod("productId")]
CommandHandlerdefined on static method acts as factory method. Given command it should return new instance of specific aggregate, in that case new Product.
CommandHandlerdefined on non static class method is place where you would put business logic and state changes