PHPackages                             lmc/cqrs-handler - 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. lmc/cqrs-handler

ActiveLibrary

lmc/cqrs-handler
================

A library containing handlers to help with Queries and Commands

2.2.0(2y ago)133.7k↓32.1%12MITPHPPHP ^8.2

Since May 13Pushed 2y ago13 watchersCompare

[ Source](https://github.com/lmc-eu/cqrs-handler)[ Packagist](https://packagist.org/packages/lmc/cqrs-handler)[ RSS](/packages/lmc-cqrs-handler/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (8)Dependencies (14)Versions (12)Used By (2)

LMC CQRS Handlers
=================

[](#lmc-cqrs-handlers)

[![cqrs-types](https://camo.githubusercontent.com/d2e4a1ae4631bc4819c80a7abc5aa314a298c371e9ab906ccf0eecdd16e00aaa/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f637172732d74797065732d707572706c652e737667)](https://github.com/lmc-eu/cqrs-types)[![Latest Stable Version](https://camo.githubusercontent.com/05a446506239f514e93538d8d3f5586c50a1880224540a76b5e13d693a6e5f6d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6c6d632f637172732d68616e646c65722e737667)](https://packagist.org/packages/lmc/cqrs-handler)[![Tests and linting](https://github.com/lmc-eu/cqrs-handler/actions/workflows/tests.yaml/badge.svg)](https://github.com/lmc-eu/cqrs-handler/actions/workflows/tests.yaml)[![Coverage Status](https://camo.githubusercontent.com/d22443a92402107799cfa36d170b3d22de360bbc35b7a4a99c0c9e9b4888f3c9/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6c6d632d65752f637172732d68616e646c65722f62616467652e7376673f6272616e63683d6d61696e)](https://coveralls.io/github/lmc-eu/cqrs-handler?branch=main)

> This library contains a base implementation for [CQRS/Types](https://github.com/lmc-eu/cqrs-types).

Table of contents
-----------------

[](#table-of-contents)

- [Installation](#installation)
- Queries
    - [Query Fetcher](#query-fetcher)
    - [Query Handlers](#query-handlers)
    - [Query](#query)
- Commands
    - [Command Sender](#command-sender)
    - [Send Command Handlers](#send-command-handlers)
    - [Command](#command)
- [ProfilerBag](#profiler-bag)

Installation
------------

[](#installation)

```
composer require lmc/cqrs-handler
```

Query Fetcher
-------------

[](#query-fetcher)

Base implementation for a Query Fetcher Interface (see [Types/QueryFetcherInterface](https://github.com/lmc-eu/cqrs-types#query-fetcher-interface)).

It is responsible for

- finding a Query Handler based on Query request type
- handle all Query features
    - caching
        - requires an instance of `Psr\Cache\CacheItemPoolInterface`
    - profiling
        - requires an instance of `Lmc\Cqrs\Handler\ProfilerBag`
- decoding a response from the Query Handler

### Usage

[](#usage)

If you are not using a [CQRS/Bundle](https://github.com/lmc-eu/cqrs-bundle) you need to set up a Query Fetcher yourself.

Minimal Initialization

```
$queryFetcher = new QueryFetcher(
    // Cache
    false,  // disabled cache
    null,   // no cache pool -> no caching

    // Profiling
    null    // no profiler bag -> no profiling
);
```

Full Initialization with all features.

```
$profilerBag = new ProfilerBag();

$queryFetcher = new QueryFetcher(
    // Cache
    true,           // is cache enabled
    $cache,         // instance of Psr\Cache\CacheItemPoolInterface

    // Profiling
    $profilerBag,   // collection of profiled information

    // Custom handlers
    // NOTE: there is multiple ways of defining handler
    [
        [new TopMostHandler(), PrioritizedItem::PRIORITY_HIGHEST],                      // Array definition of priority
        new OtherHandler(),                                                             // Used with default priority of 50
        new PrioritizedItem(new FallbackHandler(), PrioritizedItem::PRIORITY_LOWEST)    // PrioritizedItem value object definition
    ],

    // Custom response decoders
    // NOTE: there is multiple ways of defining response decoders
    [
        [new TopMostDecoder(), PrioritizedItem::PRIORITY_HIGHEST],                      // Array definition of priority
        new OtherDecoder(),                                                             // Used with default priority of 50
        new PrioritizedItem(new FallbackDecoder(), PrioritizedItem::PRIORITY_LOWEST)    // PrioritizedItem value object definition
    ]
);
```

You can add handlers and decoders by `add` methods.

```
$this->queryFetcher->addHandler(new MyQueryHandler(), PrioritizedItem::PRIORITY_MEDIUM);
$this->queryFetcher->addDecoder(new MyQueryResponseDecoder(), PrioritizedItem::PRIORITY_HIGH);
```

Fetching a query

You can do whatever you want with a response, we will persist a result into db, for an example or log an error.

```
// with continuation
$this->queryFetcher->fetch(
    $query,
    fn ($response) => $this->repository->save($response),
    fn (\Throwable $error) => $this->logger->critical($error->getMassage())
);

// with return
try {
    $response = $this->queryFetcher->fetchAndReturn($query);
    $this->repository->save($response);
} catch (\Throwable $error) {
    $this->logger->critical($error->getMessage());
}
```

Query Handlers
--------------

[](#query-handlers)

It is responsible for handling a specific Query request and passing a result into `OnSuccess` callback. [See more here](https://github.com/lmc-eu/cqrs-types#query-handler-interface).

### GetCachedHandler

[](#getcachedhandler)

This handler is automatically created `QueryFetcher` and added amongst handlers with priority `80` when an instance of `CacheItemPoolInterface` is passed into `QueryFetcher`.

It supports queries implementing `CacheableInterface` with `cacheTime > 0`. The second condition allows you to avoid caching in queries with `CacheableInterface` by just a cache time value. There is also `CacheTime::noCache()` named constructor to make it explicit.

It handles a query by retrieving a result out of a cache (if the cache has the item and is `hit` (see [PSR-6](https://www.php-fig.org/psr/psr-6/) for more).

### CallbackQueryHandler

[](#callbackqueryhandler)

This handler supports a query with request type of `"callable"`, `"Closure"` or `"callback"` (which all stands for a `callable` request).

It simply calls a created request as a function and returns a result to `OnSuccess` callback.

Query
-----

[](#query)

Query is a request which fetch a data without changing anything. [See more here](https://github.com/lmc-eu/cqrs-types#query-interface)

### CachedDataQuery

[](#cacheddataquery)

This is a predefined implementation for a Query with `CacheableInterface`.

It is handy for in-app queries where you want to use cache for a result. You can also extend it and add more features.

```
$query = new CallbackQueryHandler(
    fn () => $this->repository->fetchData(),
    new CacheKey('my-data-key'),
    CacheTime::oneHour()
);
```

### ProfiledCachedDataQuery

[](#profiledcacheddataquery)

This is a predefined implementation for a Query with `CacheableInterface` and `ProfileableInterface`.

It is handy for in-app queries where you want to use cache for a result and also profile it. You can also extend it and add more features.

```
$query = new ProfiledCallbackQueryHandler(
    fn () => $this->repository->fetchData(),
    new CacheKey('my-data-key'),
    CacheTime::oneHour(),
    'my-profiler-key',
    ['additional' => 'data']  // optional
);
```

---

Command Sender
--------------

[](#command-sender)

Base implementation for a Command Sender Interface (see [Types/CommandSenderInterface](https://github.com/lmc-eu/cqrs-types#commmand-sender-interface)).

It is responsible for

- finding a Send Command Handler based on Command request type
- handle all Command features
    - profiling
        - requires an instance of `Lmc\Cqrs\Handler\ProfilerBag`
- decoding a response from the Send Command Handler

### Usage

[](#usage-1)

If you are not using a [CQRS/Bundle](https://github.com/lmc-eu/cqrs-bundle) you need to set up a Command Sender yourself.

Minimal Initialization

```
$commandSender = new CommandSender(
    // Profiling
    null    // no profiler bag -> no profiling
);
```

Full Initialization with all features.

```
$profilerBag = new ProfilerBag();

$commandSender = new CommandSender(
    // Profiling
    $profilerBag,   // collection of profiled information

    // Custom handlers
    // NOTE: there is multiple ways of defining handler
    [
        [new TopMostHandler(), PrioritizedItem::PRIORITY_HIGHEST],                      // Array definition of priority
        new OtherHandler(),                                                             // Used with default priority of 50
        new PrioritizedItem(new FallbackHandler(), PrioritizedItem::PRIORITY_LOWEST)    // PrioritizedItem value object definition
    ],

    // Custom response decoders
    // NOTE: there is multiple ways of defining response decoders
    [
        [new TopMostDecoder(), PrioritizedItem::PRIORITY_HIGHEST],                      // Array definition of priority
        new OtherDecoder(),                                                             // Used with default priority of 50
        new PrioritizedItem(new FallbackDecoder(), PrioritizedItem::PRIORITY_LOWEST)    // PrioritizedItem value object definition
    ]
);
```

You can add handlers and decoders by `add` methods.

```
$this->commandSender->addHandler(new MyCommandHandler(), PrioritizedItem::PRIORITY_MEDIUM);
$this->commandSender->addDecoder(new MyCommandResponseDecoder(), PrioritizedItem::PRIORITY_HIGH);
```

Sending a command

You can do whatever you want with a response, we will persist a result into db, for an example or log an error.

```
// with continuation
$this->commandSender->send(
    $command,
    fn ($response) => $this->repository->save($response),
    fn (\Throwable $error) => $this->logger->critical($error->getMassage())
);

// with return
try {
    $response = $this->commandSender->sendAndReturn($query);
    $this->repository->save($response);
} catch (\Throwable $error) {
    $this->logger->critical($error->getMessage());
}
```

Send Command Handlers
---------------------

[](#send-command-handlers)

It is responsible for handling a specific Command request and passing a result into `OnSuccess` callback. [See more here](https://github.com/lmc-eu/cqrs-types#send-command-handler-interface).

### CallbackSendCommandHandler

[](#callbacksendcommandhandler)

This handler supports a command with request type of `"callable"`, `"Closure"` or `"callback"` (which all stands for a `callable` request).

It simply calls a created request as a function and returns a result to `OnSuccess` callback.

Command
-------

[](#command)

Command is a request which change a data and may return result data. [See more here](https://github.com/lmc-eu/cqrs-types#command-interface)

### ProfiledDataCommand

[](#profileddatacommand)

This is a predefined implementation for a Command with `ProfileableInterface`.

It is handy for in-app commands where you want to profile it. You can also extend it and add more features.

```
$command = new ProfiledDataCommand(
    fn () => $this->repository->fetchData(),
    new CacheKey('my-data-key'),
    CacheTime::oneHour(),
    'my-profiler-key',
    ['additional' => 'data']  // optional
);
```

ProfilerBag
-----------

[](#profilerbag)

Service, which is a collection of all profiler information in the current request. If you pass it to the `QueryFetcher` or `CommandSender`, they will profile query/command implementing `ProfileableInterface` to the `ProfilerBag`.

The information inside are used by a `CqrsDataCollector`, which shows them in the Symfony profiler (used in [CQRS/Bundle](https://github.com/lmc-eu/cqrs-bundle)).

### Verbosity

[](#verbosity)

Profiler bag can also hold an information about a verbosity level of profiling.

Levels:

- NORMAL = `empty value` (**default**)
- VERBOSE = `'verbose'`
- DEBUG = `'debug'`

There might be additional data added to the `ProfilerItem` with higher levels of verbosity.

You can set it by

```
$profilerBag->setVerbosity(ProfilerBag::VERBOSITY_VERBOSE);
```

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity31

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity71

Established project with proven stability

 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.

###  Release Activity

Cadence

Every ~128 days

Recently: every ~181 days

Total

9

Last Release

804d ago

Major Versions

1.3.0 → 2.0.02022-04-27

PHP version history (3 changes)1.0.0PHP ^7.4

2.0.0PHP ^8.1

2.2.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/2bdf0b9957c08a48e70a52fce74fc4f1add30b12d442450d5e2b48854fc98b21?d=identicon)[MortalFlesh](/maintainers/MortalFlesh)

---

Top Contributors

[![MortalFlesh](https://avatars.githubusercontent.com/u/6317184?v=4)](https://github.com/MortalFlesh "MortalFlesh (32 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/lmc-cqrs-handler/health.svg)

```
[![Health](https://phpackages.com/badges/lmc-cqrs-handler/health.svg)](https://phpackages.com/packages/lmc-cqrs-handler)
```

###  Alternatives

[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[kreait/firebase-php

Firebase Admin SDK

2.4k39.7M72](/packages/kreait-firebase-php)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

595.2M386](/packages/shopware-core)[ec-cube/ec-cube

EC-CUBE EC open platform.

78527.0k1](/packages/ec-cube-ec-cube)[neos/flow

Flow Application Framework

862.0M451](/packages/neos-flow)

PHPackages © 2026

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