whsv26/mediator

There is no license information available for the latest version (2.0.1) of this package.
Maintainers

👁 whsv26

Package info

github.com/whsv26/mediator

Type:symfony-bundle

pkg:composer/whsv26/mediator

Statistics

Installs: 37

Dependents: 0

Suggesters: 0

Stars: 4

Open Issues: 0

2.0.1 2022-01-10 09:54 UTC

Requires

Suggests

None

Provides

None

Conflicts

None

Replaces

None

Unknown License 6780dd6c2c394f1aa0d1e00cd2f6fa3c7d6e6fb3

  • whsv26 <whsv26.woop@gmail.com>

This package is auto-updated.

Last update: 2026-06-10 20:15:40 UTC


README

$ composer require whsv26/mediator

Bundle configuration

// config/packages/mediator.php

return static function (MediatorConfig $config) {
 $config->bus()
 ->query('query.bus') // query bus service id
 ->command('command.bus') // command bus service id
 ->event('event.bus'); // event bus service id
};

Enable psalm plugin (optional)

To check command and query return type compatibility with corresponding handler return type

$ vendor/bin/psalm-plugin enable Whsv26\\Mediator\\Psalm\\Plugin

Commands

/**
 * @implements CommandInterface<UserId>
 */
class CreateUserCommand implements CommandInterface
{
 public function __construct(
 public readonly string $email,
 public readonly string $password,
 ) { }
}

class CreateUserCommandHandler implements MessageHandlerInterface
{
 public function __construct(
 private readonly UserRepository $users,
 private readonly HasherInterface $hasher,
 private readonly ClockInterface $clock,
 private readonly MediatorInterface $mediator,
 ) { }

 public function __invoke(CreateUserCommand $command): UserId
 {
 $user = new User(
 UserId::next(),
 new Email($command->email),
 new PlainPassword($command->password),
 $this->hasher,
 $this->clock
 );

 $this->users->save($user);

 // Publish domain events to subscribers 
 $this->mediator->publish($user->pullDomainEvents());

 return $user->getId();
 }
}

class CreateUserAction
{
 public function __construct(
 private readonly MediatorInterface $mediator
 ) { }

 #[Route(path: '/users', name: self::class, methods: ['POST'])]
 public function __invoke(CreateUserCommand $createUser): string
 {
 // $createUser deserialized from request body
 // via custom controller argument value resolver
 
 return $this->mediator
 ->sendCommand($createUser)
 ->value;
 }
}

Queries

/**
 * @implements QueryInterface<Option<User>>
 */
class FindUserQuery implements QueryInterface
{
 public function __construct(
 public readonly ?string $id = null,
 public readonly ?string $email = null,
 ) { }
}

class FindUserQueryHandler implements MessageHandlerInterface
{
 public function __construct(
 private readonly UserRepository $users,
 ) { }

 /**
 * @param FindUserQuery $query
 * @return Option<User>
 */
 public function __invoke(FindUserQuery $query): Option
 {
 return Option::fromNullable($query->id)
 ->map(fn(string $id) => new UserId($id))
 ->flatMap(fn(UserId $id) => $this->users->findById($id))
 ->orElse(fn() => Option::fromNullable($query->email)
 ->map(fn(string $email) => new Email($email))
 ->flatMap(fn(Email $email) => $this->users->findByEmail($email))
 );
 }
}