PHPackages                             pmg/queue-tactician - 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. [Queues &amp; Workers](/categories/queues)
4. /
5. pmg/queue-tactician

ActiveLibrary[Queues &amp; Workers](/categories/queues)

pmg/queue-tactician
===================

Run your asynchronous jobs with Tactician

v7.1.0(2mo ago)153.3k↓50%11Apache-2.0PHPPHP ^8.4CI passing

Since Aug 26Pushed 2mo ago15 watchersCompare

[ Source](https://github.com/AgencyPMG/queue-tactician)[ Packagist](https://packagist.org/packages/pmg/queue-tactician)[ RSS](/packages/pmg-queue-tactician/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (2)Dependencies (9)Versions (17)Used By (1)

pmg/queue-tactician
===================

[](#pmgqueue-tactician)

This is a middleware for [Tactician](http://tactician.thephpleague.com/) to integrate it with [pmg/queue](https://github.com/AgencyPMG/Queue).

Installation and Usage
----------------------

[](#installation-and-usage)

Install with composer.

```
composer require pmg/queue-tactician

```

To use it, add the middleware to your middleware chain sometime before the default command handler middleware.

```
use League\Tactician\CommandBus;
use League\Tactician\Handler\CommandHandlerMiddleware;
use PMG\Queue\Producer;
use PMG\Queue\Tactician\QueueingMiddleware;

/** @var Producer */
$producer = createAQueueProducerSomehow();

$bus = new CommandBus([
    new QueueingMiddleware($producer),
    new CommandHandlerMiddleware(/*...*/),
]);
```

Enqueueing Commands
-------------------

[](#enqueueing-commands)

Any command that implements `PMG\Queue\Message` will be put into the queue via the producer and no further middlewares will be called.

```
use PMG\Queue\Message;

final class DoLongRunningStuff implements Message
{
    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'LongRunningStuff';
    }
}

// goes right into the queue
$bus->handle(new DoLongRunningStuff());
```

Dequeueing (Consuming) Commands
-------------------------------

[](#dequeueing-consuming-commands)

To use tactician to process the messages via the consumer, use `PMG\Queue\Handler\TacticianHandler`.

```
use PMG\Queue\DefaultConsumer;
use PMG\Queue\Handler\TacticianHandler;

/** @var League\Tactician\CommandBus $bus */
$handler = new TacticianHandler($bus);

/** @var PMG\Queue\Driver $driver */
$consumer = new DefaultConsumer($driver, $handler);

$consumer->run();
```

The above assumes that the `CommandBus` instance still has the `QueueingMiddleware` installed. If not, you'll need to use your own handler that invokes the command bus, perhaps via `CallableHandler`.

```
use League\Tactician\CommandBus;
use League\Tactician\Handler\CommandHandlerMiddleware;
use PMG\Queue\DefaultConsumer;
use PMG\Queue\Message;
use PMG\Queue\Handler\CallableHandler;

// no QueueingMiddleware!
$differentBus = new CommandBus([
    new CommandHandlerMiddleware(/*...*/),
]);

$handler = new CallableHandler([$bus, 'handle']);

/** @var PMG\Queue\Driver $driver */
$consumer = new DefaultConsumer($driver, $handler);

$consumer->run();
```

Beware of Wrapping This Handler with `PcntlForkingHandler`
----------------------------------------------------------

[](#beware-of-wrapping-this-handler-with-pcntlforkinghandler)

The shared instance of the command bus means that it's very likely that things like open database connections will cause issues if/when a child press is forked to handle messages.

Instead a better bet is to create a new command bus for each message. `CreatingTacticianHandler` can do that for you.

```
use League\Tactician\CommandBus;
use League\Tactician\Handler\CommandHandlerMiddleware;
use PMG\Queue\Message;
use PMG\Queue\Handler\CallableHandler;
use PMG\Queue\Tactician\QueuedCommand;
use PMG\Queue\Tactician\QueueingMiddleware;
use PMG\Queue\Handler\CreatingTacticianHandler;

$handler = new CreatingTacticianHandler(function () {
    // this is invoked for every message
    return new CommandBus([
        new QueueingMiddleware(createAProduerSomehow()),
        new CommandHandlerMiddlware(/* ... */)
    ]);
});

/** @var PMG\Queue\Driver $driver */
$consumer = new DefaultConsumer($driver, $handler);

$consumer->run();
```

###  Health Score

60

—

FairBetter than 99% of packages

Maintenance88

Actively maintained with recent releases

Popularity29

Limited adoption so far

Community20

Small or concentrated contributor base

Maturity89

Battle-tested with a long release history

 Bus Factor1

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

Every ~350 days

Recently: every ~290 days

Total

12

Last Release

61d ago

Major Versions

2.0.0 → 3.0.02016-08-26

3.0.0 → 4.0.02017-08-31

4.0.0 → v5.0.02020-03-31

v5.1.0 → v6.0.02023-01-12

v6.2.0 → v7.0.02026-01-15

PHP version history (5 changes)v5.1.0PHP ^7.4 || ^8.0

v6.0.0PHP ^8.0

v6.1.0PHP ^8.2

v6.2.0PHP ^8.3

v7.1.0PHP ^8.4

### Community

Maintainers

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

---

Top Contributors

[![chrisguitarguy](https://avatars.githubusercontent.com/u/1010392?v=4)](https://github.com/chrisguitarguy "chrisguitarguy (29 commits)")[![jrughani9](https://avatars.githubusercontent.com/u/108751272?v=4)](https://github.com/jrughani9 "jrughani9 (12 commits)")[![jimfurnier](https://avatars.githubusercontent.com/u/23461159?v=4)](https://github.com/jimfurnier "jimfurnier (2 commits)")[![jonbernardi](https://avatars.githubusercontent.com/u/38191?v=4)](https://github.com/jonbernardi "jonbernardi (2 commits)")[![WebCu](https://avatars.githubusercontent.com/u/3429093?v=4)](https://github.com/WebCu "WebCu (2 commits)")[![jimfurnierpmg](https://avatars.githubusercontent.com/u/163916393?v=4)](https://github.com/jimfurnierpmg "jimfurnierpmg (1 commits)")

---

Tags

command-busphppmg-queuepmg-queue-driverqueuetacticianqueuecommandbus

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/pmg-queue-tactician/health.svg)

```
[![Health](https://phpackages.com/badges/pmg-queue-tactician/health.svg)](https://phpackages.com/packages/pmg-queue-tactician)
```

###  Alternatives

[php-amqplib/php-amqplib

Formerly videlalvaro/php-amqplib. This library is a pure PHP implementation of the AMQP protocol. It's been tested against RabbitMQ.

4.6k125.3M879](/packages/php-amqplib-php-amqplib)[ramsey/collection

A PHP library for representing and manipulating collections.

1.2k486.0M69](/packages/ramsey-collection)[queue-interop/queue-interop

Promoting the interoperability of MQs objects. Based on Java JMS

48130.5M87](/packages/queue-interop-queue-interop)[enqueue/enqueue

Message Queue Library

19820.0M56](/packages/enqueue-enqueue)[phootwork/collection

The phootwork library fills gaps in the php language and provides better solutions than the existing ones php offers.

3924.8M15](/packages/phootwork-collection)[apinstein/jqjobs

Async job manager for PHP.

3220.2k](/packages/apinstein-jqjobs)

PHPackages © 2026

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