Open-source project
laminas/laminas-eventmanager avatar
laminas/laminas-eventmanager

laminas-eventmanager: a small event manager for PHP applications

Trigger and listen to events within a PHP application

1,016 stars19 forksPHPBSD-3-Clause

At a glance

What is it?
laminas-eventmanager is a compact PHP library for named events, letting you attach and detach listeners per instance or through shared collections, trigger events, and interrupt the execution of listeners. It is a dependency of a handful of packages rather than a framework, it keeps a maintenance branch per release line, and the README describes its architecture in a single paragraph.
Who is it for?
Adopt laminas-eventmanager if you are building a PHP library or application that needs decoupled listeners, if you want the same event manager that other Laminas components use, and if you can work with the API of a single major version. Do not adopt it for a single event between two classes, where a direct call is clearer.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A named event bus, and the three shapes it takes

laminas-eventmanager describes itself in one line as a tool to trigger and listen to events within a PHP application, and then lists the use cases it is designed for. It is for implementing simple subject and observer patterns, for implementing Aspect-Oriented designs, and for implementing event-driven architectures.

Those three are worth separating, because they are not the same requirement wearing different clothes. A subject and observer pattern is a one to many notification within an object graph. An aspect oriented design wants to run code around a call, before and after, which is an event with a very specific shape. An event driven architecture wants named events on a shared bus, decoupled from who produces them.

The library serves all three with the same core, which is why it is a dependency in more than one kind of project. The name of the package is the same as the repository, laminas/laminas-eventmanager, and the documentation is published at docs.laminas.dev/laminas-eventmanager.

What it is not is a framework or a bus with a message queue behind it. There is no persistence, no serialisation of events, no transport. It is an in-process mechanism, and the unit of work is a listener call inside the same PHP process that triggered it.

Attach, detach, trigger and interrupt

The architecture description in the README is short and complete. The basic architecture allows you to attach and detach listeners to named events, both on a per-instance basis as well as via shared collections, to trigger events, and to interrupt execution of listeners.

Four capabilities, and each one answers a question that comes up immediately in practice.

Named events are the first. A listener is bound to a name rather than to an object, which is what makes the decoupling possible and what lets a producer that knows nothing about its consumers announce that something happened.

Per instance and shared collections is the second, and it is the part that decides how the library is used. A listener attached to one event manager instance only ever hears events triggered through that instance. A listener in a shared collection hears events from every manager that shares it. The first is scoped, the second is global, and most real applications need both, which is why both are in the core rather than in an extension.

Detaching is the third, and it matters more than it sounds. A listener you cannot remove is a leak, and in a long lived PHP process handling many requests, a listener attached per request is a memory leak. The API supports removal for that reason.

Interruption is the fourth, and it is the least obvious. A listener can stop the execution of the remaining listeners, which is how an aspect that decides the result of an operation short circuits the chain. It is a power tool, and it is also the mechanism by which a badly written listener can silently swallow events that other parts of the system depend on.

The branch layout tells you which line you are on

The default branch in the repository's own metadata is 3.16.x, and the release history is a maintenance branch per line. The recent tags are 3.13.1 from 2024-06-24, 3.14.0 from 2024-11-21 and 3.15.0 from 2025-10-31.

So the branch you are reading is ahead of the newest release, which is the normal shape for a package that keeps a maintenance branch per minor version: the 3.16.x branch is where 3.16 is developed, and it is not yet cut as a tag.

The last push was on 2026-10-19 and the repository is not archived, so the work is ongoing. The support policy, which for a package with several live branches is the question that matters to a team deciding whether to adopt it, is worth checking. The project is part of the Laminas organisation, and the presence of a COPYRIGHT.md file, a psalm configuration with a baseline, a phpcs configuration, a phpunit configuration and a renovate configuration in the repository root is the sort of setup that a foundation maintained package tends to have.

The migration question is signposted too. For migration from version 2 to version 3, the README points at a migration document in the documentation site. Version 3 was a real API change, and the note exists because a project that has been on version 2 for a decade has work to do here.

The benchmarks live in the repository and run with PHPBench

The library ships its own performance harness, which is unusual for a component this small and worth a look for anybody with a hot path that triggers a lot of events.

The README says it provides scripts for benchmarking laminas-eventmanager using the PHPBench framework, and that these can be found in the benchmarks/ directory. To execute the benchmarks you run:

bash
$ vendor/bin/phpbench run --report=aggregate

The surrounding configuration tells you how the project is put together. There is a phpbench.json at the root holding the benchmark configuration, and a phpunit.xml.dist for the unit tests. Static analysis is done with psalm, with a psalm/ directory and a psalm-baseline.xml that records the known findings so that new ones are caught. Style is checked with phpcs.xml. The documentation is written in Markdown with an mkdocs.yml, and the doc/ directory holds the source. The continuous integration configuration lives in.laminas-ci.json, which is the shared runner configuration the Laminas projects use.

There is also a file called structarmed.php in the repository root, and a test/ directory. The presence of a psalm baseline is a small but useful signal: it means the project tracks its static analysis findings rather than suppressing them wholesale, which is what you want to know when you are deciding whether to depend on a package for a long time.

Where a small event manager is the wrong tool

The limits of a component like this are mostly about expectations, and the README itself is thin on the features a reader might assume are there.

The first is that the visible documentation describes a small API. Named events, listeners, attach, detach, trigger, and interruption. The README does not mention listener priority, wildcard event names, asynchronous delivery, or any persistence of events, and the documentation site is where those questions are answered or not answered. A reader who assumes the feature set of a larger dispatcher will be disappointed, and it is better to check the API reference before designing around something that is not there.

The second is scope. If you have one event between two classes that you control, a direct method call is clearer, faster and easier to follow than an event, and an event manager turns a compile time relationship into a runtime one that a reader has to discover. The library is for the cases where the producer should not know the consumers, and for aspect style behaviour that has to wrap calls.

The third is the process boundary. Everything happens in the same PHP process, synchronously, in the order the listeners were attached unless a listener interrupts. If the work you want to trigger belongs in another process, in a queue, or in a background worker, this is not the mechanism, and no amount of configuration will make it one.

The fourth is the version spread. The package is on major version 3, with several minor lines alive at once, and there is a documented migration path from version 2. An application with a long life and a conservative upgrade policy should plan for the branch it is on rather than the newest tag, since the default branch the repository serves is 3.16.x while the newest release is 3.15.0.

Editorial conclusion

Adopt laminas-eventmanager if you are building a PHP library or application that needs decoupled listeners, if you want the same event manager that other Laminas components use, and if you can work with the API of a single major version. Do not adopt it for a single event between two classes, where a direct call is clearer. Verify first which release line you are on, since the default branch is 3.16.x while the newest tagged release is 3.15.0, read the version 2 to 3 migration notes if you are upgrading an older installation, and check the API documentation for the features the README does not describe.

Frequently asked questions

What is laminas-eventmanager used for?

The README lists three use cases: implementing simple subject and observer patterns, implementing Aspect-Oriented designs, and implementing event-driven architectures. The basic architecture allows you to attach and detach listeners to named events, per instance or through shared collections, to trigger events, and to interrupt execution of listeners.

How do I run the laminas-eventmanager benchmarks?

The benchmarking scripts use the PHPBench framework and live in the benchmarks/ directory of the repository. The README gives the command as vendor/bin/phpbench run --report=aggregate, with the phpbench.json file at the repository root holding the configuration.

Which laminas-eventmanager version should I use?

The repository's default branch is 3.16.x while the newest tagged release is 3.15.0 from 2025-10-31, with 3.14.0 and 3.13.1 also maintained. The README points at a migration document for anyone moving from version 2 to version 3.

Does laminas-eventmanager support asynchronous events?

The README describes attaching and detaching listeners to named events, triggering events and interrupting execution of listeners, all in process. It does not mention asynchronous delivery, listener priorities or wildcard event names, so the API documentation at docs.laminas.dev/laminas-eventmanager is the place to check for those.

Official sources

  1. laminas/laminas-eventmanager on GitHub
  2. License: BSD-3-Clause
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/laminas-laminas-eventmanager.svg)](https://hysenlabs.com/projects/laminas-laminas-eventmanager)

Was this useful?