Links

Fetching and Querying Aggregate

Ecotone comes with inbuilt repositories like Event Sourcing Repository or State-Stored Repository backed by Document Store, which means if chose you don't need to implement any of this.
In some cases you may want to actually fetch aggregate instance directly, and keep your business code decoupled from the the framework. That's why Ecotone introduced interface based repositories.

Interface Based Repository

In order to fetch aggregates you may introduce interface repository:
interface OrderRepository
{
// 1. nullable return type
#[Repository]
public function findBy(string $orderId): ?Order;
// 2. non-nullable return type
#[Repository]
public function getBy(string $orderId): Order;
}
Ecotone based on return type class will find corresponding repository, that can handle fetching given aggregate.
  1. 1.
    Nullable return type - In case return type is nullable, Ecotone will return null, if aggregate is not found.
  2. 2.
    Non-nullable return type - In case return type is non-nullable, it will throw AggregateNotFoundException if aggregate is not found.
As Repository is another type of Gateway, Ecotone will provide implemention for you, which will be available in your Dependency Container.

In Memory implementations

The next benefit of the above solution is abstracting away persistence layer. If you will switch to In Memory repository implementations, everything will continue to work.

Aggregate Query Handler

You may put query handler on your aggregate, to fetch the state.
#[EventSourcingAggregate]
class Twitter
{
(...)
#[QueryHandler('getContent')]
public function getContent(): string
{
return $this->content;
}
}
$result = $queryBus->sendWithRouting (
'getContent',
// this is how we tell Ecotone aggregate identifier to fetch
metadata: ["aggregate.id" => $twitterId]
);
Ecotone will resolve the aggregrate by aggregate.id header and call the method for you.
You may of course pass query object like with any other Query Handler

Exposing state via Business Interface

In case you would like to call aggregate to fetch the state or to make some calculations, Ecotone allows you to build API via interface. This way you may skip using QueryBus and work with your own business interface.
interface TwitterApi
{
#[MessageGateway('getContent')]
public function getContent(#[AggregateIdentifier] string $twitId): string;
}
The same applies to Commands, if you would like to you may expose Command Handlers via MessageGateway.

Demo

You can check demo to see how to work with Aggregate Interface Repositories or Business Interfaces.