PHPackages                             thepsion5/admiral - 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. [CLI &amp; Console](/categories/cli)
4. /
5. thepsion5/admiral

ActiveLibrary[CLI &amp; Console](/categories/cli)

thepsion5/admiral
=================

Simple PHP Command Bus Implementation

29PHP

Since Jul 24Pushed 11y ago1 watchersCompare

[ Source](https://github.com/thepsion5/admiral)[ Packagist](https://packagist.org/packages/thepsion5/admiral)[ RSS](/packages/thepsion5-admiral/feed)WikiDiscussions master Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

\#Admiral [![Build Status](https://camo.githubusercontent.com/2e7ccd728e72e7f9d4f96f268cee66363337857a0e3d42ef93fd957c37eb3813/68747470733a2f2f7472617669732d63692e6f72672f7468657073696f6e352f61646d6972616c2e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/thepsion5/admiral)[![Coverage Status](https://camo.githubusercontent.com/72ab216f3200fd5b44ed0b991c934e722ccaf4d42eefc44702acbf7761ca25de/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f7468657073696f6e352f61646d6972616c2f62616467652e706e673f6272616e63683d6d6173746572)](https://coveralls.io/r/thepsion5/admiral?branch=master)A simple but flexible PHP implementation of the Command Bus pattern. ##Installation Add the package to your composer.json file:

```
{
    "require": {
        "thepsion5/admiral" : "dev-master"
    }
}
```

Then run `composer update`

\##Basic Usage In this context, a command is a DTO representing a single high-level instruction for an application. Let's consider an application for managing music playlists. We need four things:

1. A command class implementing `\Thepsion5\Admiral\CommandInterface`
2. A handler class implementing `\Thepsion5\Admiral\CommandHandlerInterface`
3. A class that creates the command instance and passes it to the Command Bus

\###Create a Command

```
class AddAlbumToLibraryCommand implements \Thepsion5\Admiral\CommandInterface
{
    public $albumName;
    public $artistId;
    public $songs = [];

    public function __construct($artistId, $albumName, array $songs)
    {
        $this->artistId = $artistId;
        $this->albumName = $albumName;
        $this->songs = $songs;
    }
}
```

\###Create the Corresponding Command Handler

```
class AddAlbumToLibraryCommandHandler implements \Thepsion5\Admiral\CommandHandlerInterface
{
    public function handle(AddAlbumToLibraryCommand $command)
    {
        //perform business logic here
    }
}
```

\###Execute the Command

```
class AdminController
{
    public function __construct()
    {
        $this->commandBus = \Thepsion5\Admiral\CommandBusFactory::makeCommandBus();
    }

    function postUploadAlbum($artistId)
    {
        $input = $this->input->post();
        $command = new AddAlbumToLibraryCommand($artistId, $input['title'], $input['songs']);
        $this->commandBus->execute($command);
    }
}
```

The Command Bus will automatically attempt to resolve the name of the command class into a handler by replacing 'Command' with 'CommandHandler'. So, `Acme\Domain\Albums\AddAlbumToLibraryCommand` will be translated to `Acme\Domain\Albums\AddAlbumToLibraryCommandHandler`. Next, the Command Bus will create the handler and return the results of the `handle` function.

\##Advanced Usage

\###Manually Registering Command Handlers If you have a different naming convention for commands and handlers, you may register handlers manually:

```
$resolver = $commandBus->getResolver();
$resolver->register('Acme\Commands\AddAlbumToLibrary', 'Acme\Handlers\AddAlbumToLibrary');
```

You can also use a custom resolver by implementing `Thepsion5\Admiral\CommandHandlerResolverInterface` and setting it manually:

```
$resolver = new AcmeCommandHandlerResolver();
$commandBus->setResolver($resolver);
```

\###Dependency Injection in Handlers For handlers with external dependencies, Admiral supports the use of Dependency Injection using `illuminate/container`, the DI Container that powers the Laravel framework. It can be accessed via the `getContainer()` method on the command handler:

```
$container = $commandBus->getResolver()->getContainer();
```

The container implements `Thepsion5\Admiral\Container\ContainerInterface`. Bindings can be configured like so:

```
$container->bind(
    'Acme\Domain\Albums\AlbumRepositoryInterface',
    '\Acme\Infrastructure\Albums\DbAlbumRepository'
);
//returns an instance of DbAlbumRepository
$repository = $container->make('Acme\Domain\Albums\AlbumRepositoryInterface');
```

\###Using Other DI Containers

You can use a custom DI Container by creating an adapter that implements `ContainerInterface`:

```
$commandBus->getResolver()->setContainer(new SymfonyDiContainer);
```

\##Access Control

Additional ACL functionality can be added to the Command Bus to provide fine-grained control over who is capable of executing commands, without having to add that functionality to the command handlers.

To use this feature, we need to use two additional components:

1. An `AccessControlCommandBus` instance
2. An `AccessPolicy` class

\###Creating the Command Bus and Access Policy Class

The `AccessControlCommandBus` can be instantiated using the factory:

```
$commandBus = \Thepsion5\Admiral\CommandBusFactory::makeAccessControlCommandBus();
```

This instance works no differently than the standard command bus but allows for the use of an Access Policy Class. The method used to resolve it is similar to that used to resolve the command handler. For example `CreateAlbumCommand` would look for a `CreateAlbumAccessPolicy`in the same namespace.

Here's an example Access Policy class:

```
class CreateAlbumAccessPolicy implements \Thepsion5\Admiral\AccessControl\AccessPolicyInterface
{
    public function assess(CommandInterface $command)
    {
        if(!Auth::user()) {
            throw new AccessControlException("You must be logged in to create an album.");
        } elseif(!Auth::user()->owns($command->artistId)) {
            throw new AccessControlException("You can only create Album for an artist you own.");
        }
    }
}
```

If no matching class is found, it will be ignored and the handler class will be called normally.

\##Todo

- More documentation on Access Control

###  Health Score

20

—

LowBetter than 14% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity7

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/59b85632c6b77d0364d849b60ed2ca9de84745c09559d9f2f1b5e1c9a629900a?d=identicon)[thepsion5](/maintainers/thepsion5)

---

Top Contributors

[![thepsion5](https://avatars.githubusercontent.com/u/2222722?v=4)](https://github.com/thepsion5 "thepsion5 (11 commits)")

### Embed Badge

![Health badge](/badges/thepsion5-admiral/health.svg)

```
[![Health](https://phpackages.com/badges/thepsion5-admiral/health.svg)](https://phpackages.com/packages/thepsion5-admiral)
```

###  Alternatives

[wp-cli/wp-cli

WP-CLI framework

5.0k17.2M319](/packages/wp-cli-wp-cli)[consolidation/annotated-command

Initialize Symfony Console commands from annotated command class methods.

22569.8M18](/packages/consolidation-annotated-command)[chi-teck/drupal-code-generator

Drupal code generator

26947.8M5](/packages/chi-teck-drupal-code-generator)[seld/cli-prompt

Allows you to prompt for user input on the command line, and optionally hide the characters they type

24725.8M17](/packages/seld-cli-prompt)[illuminate/console

The Illuminate Console package.

12944.1M5.1k](/packages/illuminate-console)[php-tui/php-tui

Comprehensive TUI library heavily influenced by Ratatui

589747.0k6](/packages/php-tui-php-tui)

PHPackages © 2026

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