PHPackages                             smartgecko/governor-framework - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. smartgecko/governor-framework

ActiveLibrary[Framework](/categories/framework)

smartgecko/governor-framework
=============================

PHP Command-Query-Responsibility-Segregation framework.

0.3.0(11y ago)11332612[4 issues](https://github.com/SmartGecko/GovernorFramework/issues)MITPHPPHP 5.5.\*

Since Dec 14Pushed 10y ago12 watchersCompare

[ Source](https://github.com/SmartGecko/GovernorFramework)[ Packagist](https://packagist.org/packages/smartgecko/governor-framework)[ RSS](/packages/smartgecko-governor-framework/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (18)Versions (5)Used By (0)

Governor Framework PHP CQRS library
===================================

[](#governor-framework-php-cqrs-library)

[![Build Status](https://camo.githubusercontent.com/9a10a330a98a234222df3ad9ff1db1c29b086263857f5dd9f6731d584f17a52c/68747470733a2f2f7472617669732d63692e6f72672f536d6172744765636b6f2f476f7665726e6f724672616d65776f726b2e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/SmartGecko/GovernorFramework)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/4cd2946314ed710a990945d7ecb8204308f60f6ba26e82b2f06d261bf6df2aac/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f536d6172744765636b6f2f476f7665726e6f724672616d65776f726b2f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/SmartGecko/GovernorFramework/?branch=master)[![Code Coverage](https://camo.githubusercontent.com/3ef6c66b7808a63634b55d38a1c89900f76d42e557b193e94439c79013d0055e/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f536d6172744765636b6f2f476f7665726e6f724672616d65776f726b2f6261646765732f636f7665726167652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/SmartGecko/GovernorFramework/?branch=master)

Governor Framework is a Command and Query Responsibility Segregation library for PHP 5.5+.

It provides components to build applications following the CQRS patterns such as:

- Command Handling
- Event Handling
- Event Sourcing
- Event Stores
- Sagas
- Unit Of Work
- Repositories
- Serialization
- AMQP support
- Testing

The main source of inspiration for this library was the [Axon Framework](http://www.axonframework.org/ "Axon Framework") written in Java and the Governor Framework can be viewed as a PHP port of the Axon, because it retains its basic building blocks.

The library can be directly integrated into the Symfony 2 framework as a bundle. The core of the Symfony 2 integration was taken from the [LiteCQRS framework](https://github.com/beberlei/litecqrs-php).

Quick Start
===========

[](#quick-start)

The Domain Model
----------------

[](#the-domain-model)

To demonstrate the features of the Governor Framework we will work with a rather simple User model. The User class is our aggregate root. Aggregate roots in Governor must either implement the `Governor\Framework\Domain\AggregateRootInterface` interface or extend one of the built in base classes:

- `Governor\Framework\Domain\AbstractAggregateRoot`
- `Governor\Framework\EventSourcing\AbstractEventSourcedAggregateRoot`
- `Governor\Framework\EventSourcing\Annotation\AbstractAnnotatedAggregateRoot`

In this example we will use the aggregate root with annotation support. Our aggregate will also serve as a command handler in this example.

The aggregate will react to the commands

- `CreateUserCommand`
- `ChangeUserEmailCommand`

which will produce the corresponding events

- `UserCreatedEvent`
- `UserEmailChangedEvent`

Our aggregate root implementation will look the following.

```
class User extends AbstractAnnotatedAggregateRoot
{
    /**
     * @AggregateIdentifier
     * @var string
     */
    private $identifier;
    private $email;

    /**
     * @CommandHandler
     * @param CreateUserCommand $command
     */
    public function __construct(CreateUserCommand $command)
    {
        $this->apply(new UserCreatedEvent($command->getIdentifier(), $command->getEmail()));
    }

    /**
     * @CommandHandler
     * @param ChangeUserEmailCommand $command
     */
    public function changeEmail(ChangeUserEmailCommand $command)
    {
        $this->apply(new UserEmailChangedEvent($this->identifier, $command->getEmail()));
    }

    /**
     * @EventHandler
     * @param UserEmailChangedEvent $event
     */
    public function onEmailChanged(UserEmailChangedEvent $event)
    {
        $this->email = $event->getEmail();
    }

    /**
     * @EventHandler
     * @param UserCreatedEvent $event
     */
    public function onUserCreated(UserCreatedEvent $event)
    {
        $this->identifier = $event->getIdentifier();
        $this->email = $event->getEmail();
    }

    public function getEmail()
    {
        return $this->email;
    }

}
```

Commands and Events
-------------------

[](#commands-and-events)

We introduce 2 operations over the aggregate - one will create a new user and the second will change the user email. Notice the `@Type` annotations on the event class - Governor Framework uses the excellent JMS serializer library for serialization and deserialization purposes. To allow event deserialization when rebuilding the aggregate from an event stream the annotations must be present in order to successfully deserialize the events.

Our commands and events are implemented like this:

```
abstract class AbstractUserEvent
{

    /**
     * @Type("string")
     * @var string
     */
    private $identifier;

    /**
     * @Type("string")
     * @var string
     */
    private $email;

    function __construct($identifier, $email)
    {
        $this->identifier = $identifier;
        $this->email = $email;
    }

    public function getIdentifier()
    {
        return $this->identifier;
    }

    public function getEmail()
    {
        return $this->email;
    }

}

class UserCreatedEvent extends AbstractUserEvent
{

}

class UserEmailChangedEvent extends AbstractUserEvent
{

}

abstract class AbstractUserCommand
{
    /**
     * @TargetAggregateIdentifier
     * @var string
     */
    private $identifier;
    private $email;

    function __construct($identifier, $email)
    {
        $this->identifier = $identifier;
        $this->email = $email;
    }

    public function getIdentifier()
    {
        return $this->identifier;
    }

    public function getEmail()
    {
        return $this->email;
    }

}

class CreateUserCommand extends AbstractUserCommand
{

}

class ChangeUserEmailCommand extends AbstractUserCommand
{

}
```

Event listeners
---------------

[](#event-listeners)

We can register event listeners to listen for events on the event bus. The event listeners need to implement the `Governor\Framework\EventHandling\EventListenerInterface` interface.

This simple listener that will listen for all events on the event bus and print their payload.

```
class UserEventListener implements EventListenerInterface
{

    public function handle(EventMessageInterface $event)
    {
        print_r($event->getPayload());
    }

}
```

Wrapping it all together
------------------------

[](#wrapping-it-all-together)

Now we can complete the example by setting up the necessary infrastructure in the following steps

1. We need to set up a PSR-0 compatible logger like Monolog.
2. Create a command bus and for convienience wrap it in a command gateway.
3. Initialize an event store backed by a filesystem. Note that if you don't want to use event sourcing this step can be skipped.
4. Set up a simple event bus
5. Create an event sourcing repository
6. Subscribe the annotated aggregate root to the command bus so it can recieve commands.
7. Register an event listener that will display the content of our events.
8. Dispatch commands.

```
// set up logging
$logger = new Logger('governor');
$logger->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG));

// 1. create a command bus and command gateway
$commandBus = new SimpleCommandBus();
$commandBus->setLogger($logger);
$commandGateway = new DefaultCommandGateway($commandBus);

$rootDirectory = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'CommandHandlerExample';
@mkdir($rootDirectory);
echo sprintf("Initializing FileSystemEventStore in %s\n", $rootDirectory);

// 2. initialize the event store
$eventStore = new FilesystemEventStore(new SimpleEventFileResolver($rootDirectory),
    new JMSSerializer());

// 3. create the event bus
$eventBus = new SimpleEventBus();
$eventBus->setLogger($logger);

// 4. create an event sourcing repository
$repository = new EventSourcingRepository(User::class,
    $eventBus, new NullLockManager(), $eventStore,
    new GenericAggregateFactory(User::class));

//5. create and register our commands
AnnotatedAggregateCommandHandler::subscribe(User::class, $repository, $commandBus);

//6. create and register the eventlistener
$eventListener = new UserEventListener();
$eventBus->subscribe($eventListener);

//7. send commands
$aggregateIdentifier = Uuid::uuid1()->toString();

$commandGateway->send(new CreateUserCommand($aggregateIdentifier,
    'email@davidkalosi.com'));
$commandGateway->send(new ChangeUserEmailCommand($aggregateIdentifier,
    'newemail@davidkalosi.com'));
```

Licensing
=========

[](#licensing)

Governor Framework is licensed under the [MIT](http://opensource.org/licenses/MIT) license.

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance19

Infrequent updates — may be unmaintained

Popularity28

Limited adoption so far

Community18

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 98.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

4170d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/b648fff2b2766758ad0c7ee5de8ae24f4ec00ae5123bc8ed6c79538a6766df7f?d=identicon)[smartgecko](/maintainers/smartgecko)

---

Top Contributors

[![davidkalosi](https://avatars.githubusercontent.com/u/4612875?v=4)](https://github.com/davidkalosi "davidkalosi (135 commits)")[![jesseschalken](https://avatars.githubusercontent.com/u/1559204?v=4)](https://github.com/jesseschalken "jesseschalken (1 commits)")[![rayrutjes](https://avatars.githubusercontent.com/u/5570853?v=4)](https://github.com/rayrutjes "rayrutjes (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/smartgecko-governor-framework/health.svg)

```
[![Health](https://phpackages.com/badges/smartgecko-governor-framework/health.svg)](https://phpackages.com/packages/smartgecko-governor-framework)
```

###  Alternatives

[laravel/framework

The Laravel Framework.

34.7k509.9M17.0k](/packages/laravel-framework)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[magento/community-edition

Magento 2 (Open Source)

12.1k52.1k10](/packages/magento-community-edition)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

595.2M386](/packages/shopware-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
