PHPackages                             meraki/composition - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. meraki/composition

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

meraki/composition
==================

A deterministic DI container for PHP 8.4+ with predictable autowiring.

v1.0.0-alpha(3mo ago)016MITPHPPHP ^8.4CI passing

Since Jan 29Pushed 3mo agoCompare

[ Source](https://github.com/merakiframework/composition)[ Packagist](https://packagist.org/packages/meraki/composition)[ RSS](/packages/meraki-composition/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (2)Versions (2)Used By (0)

Meraki\\Composition
===================

[](#merakicomposition)

A **deterministic object composition container** for PHP 8.4+ with predictable autowiring.

*Meraki\\Composition* builds fully-constructed object graphs by autowiring dependencies where possible, and failing fast when resolution would be ambiguous. It never guesses: defaults are respected, nullability is honoured, and unclear intent is treated as an error rather than making an assumption.

The public API focuses on composition and intent, while wiring and resolution mechanics are kept internal. The result is a small, opinionated container designed for clarity, correctness, and long-term maintainability.

Why this library exists
-----------------------

[](#why-this-library-exists)

Most PHP DI containers blur three distinct ideas:

- **Dependency Injection (DI)** which is a technique
- **Inversion of Control (IoC)** which is a principle
- **Containers** which is infrastructure

*Meraki\\Composition* makes these boundaries explicit.

- **Composition** is the contract exposed to users
- **Wiring** is the "internal machinery" that makes composition possible

This separation keeps:

- public APIs stable (including the namespace and error semantics)
- allows the internals to evolve freely or separately
- creates a DDD-like code base for easier understanding and maintenance

Core concepts
-------------

[](#core-concepts)

### Composition (public)

[](#composition-public)

Composition answers the question:

> "How do I construct a complete and valid object graph?"

The public surface of this library lives in the `Meraki\Composition` namespace and is intentionally kept small.

Key responsibilities:

- resolving fully-constructed objects
- exposing configuration
- enforcing resolution semantics
- defining failure behavior

Primary entry points:

- `Meraki\Composition\Container`
- `Meraki\Composition\ContainerConfig`
- `Meraki\Composition\Exception` (and subclasses)

These are the only classes most users should ever need.

### Wiring (private)

[](#wiring-private)

Wiring answers the question:

> "How are dependencies connected under the hood?"

The `Meraki\Wiring` namespace contains internal implementation details such as:

- resolution algorithms
- definitions and bindings
- reflection helpers
- circular dependency detection
- resolution path tracking

These classes:

- are **not** part of the public API
- may change without notice
- should not be depended on directly
- are intentionally kept separate from `Meraki\Composition` to enforce this boundary.

They exist to support composition — nothing more.

Basic usage
-----------

[](#basic-usage)

```
use Meraki\Composition\Container;

$container = new Container();

// define object graphs you don't want auto-wired
$definition = $container->define(MyInterface::class, MyImplementation::class);

// you can tweak the returned definition as needed
// For example, make it a singleton
$definition->share();

// container is now 'immutable' and can be used
// you must re-assign the variable here (A PSR container is returned)
$container = $container->freeze();

// retrieve fully constructed services
$onj = $container->get(MyInterface::class);
```

That's it!

The container will:

- recursively resolve all constructor dependencies
- auto-wire concrete classes
- respect default values
- detect circular references
- throw explicit, meaningful exceptions when resolution fails

The container config allows you to explicitly define bindings, singletons, and other behaviors as needed.

Design principles
-----------------

[](#design-principles)

This library (and its development) is guided by a few strict principles:

- Constructor injection only
- No service locator usage
- No hidden dependencies
- Explicit failure over silent fallback
- Public APIs describe intent, not mechanism
- The container is infrastructure, domain code should not know it exists.
- Convention over configuration where reasonable
- Be as simple as possible, but not over clarity (in code and in-use)
- Should be usable in applications of any size, without trying to solve every problem
- Should 'age well' (easily maintainable, extensible, and understandable)
- Tests should clearly express intent and respect boundaries
- Avoid premature optimization; favor clarity and correctness first
- Adhere to SOLID principles
- Favor composition over inheritance

Finally, while this library can be used in any PHP application, it has been designed to be used in Domain-Driven Design (DDD) contexts, where clear boundaries and explicit dependencies are paramount. Therefore, it avoids patterns and practices that conflict with DDD principles. (For example, the container respect default values unless explicitly overridden, allowing entities and value objects to maintain their integrity without container interference.)

Directory structure
-------------------

[](#directory-structure)

The repository is structured to allow clean future extraction and independent evolution without forcing it today.

```
.
├─ composition/
│  ├─ src/
│  │  ├─ Exception/
│  │  ├─ Container.php
│  │  ├─ FrozenContainer.php
│  │  └─ etc...
│  └─ tests/
│     |─ Exception/
|     |─ Fixture/
|     └─ etc...
│
├─ wiring/
│  ├─ src/
│  │  └─ etc...
│  └─ tests/
|     ├─ Fixture/
│     └─ etc...
│
└─ integration-tests/
|     ├─ Fixture/
│     └─ etc...

```

### Why this structure?

[](#why-this-structure)

- Composition and Wiring are siblings, not nested concepts
- Each can be extracted into its own package later with minimal effort
- Public intent and internal mechanics are visually distinct
- Test boundaries are obvious

Testing strategy
----------------

[](#testing-strategy)

### Composition tests

[](#composition-tests)

Located in:

`composition/tests/`

They test:

- container contracts
- configuration behavior
- error semantics
- parameter resolution rules

And answer:

> Does the container uphold its public contract?

### Integration tests

[](#integration-tests)

Located in:

`integration-tests/`

They test:

- multi-class resolution
- deep dependency graphs
- circular dependency detection
- resolution state across multiple get() calls
- the integration between Composition and Wiring

For example, `ContainerResolutionTest` answers:

> Does the container correctly resolve real object graphs?

License
-------

[](#license)

This library is licensed under the MIT License. See the [LICENSE](LICENSE.md) file for details.

Copyright (c) 2024 Nathan Bishop

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance79

Regular maintenance activity

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

 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

Unknown

Total

1

Last Release

109d ago

### Community

Maintainers

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

---

Top Contributors

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

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/meraki-composition/health.svg)

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

###  Alternatives

[symfony/dependency-injection

Allows you to standardize and centralize the way objects are constructed in your application

4.2k431.1M7.5k](/packages/symfony-dependency-injection)[illuminate/contracts

The Illuminate Contracts package.

704122.9M10.1k](/packages/illuminate-contracts)[illuminate/container

The Illuminate Container package.

31278.1M2.0k](/packages/illuminate-container)[ecotone/ecotone

Supporting you in building DDD, CQRS, Event Sourcing applications with ease.

558549.8k17](/packages/ecotone-ecotone)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

728272.9k20](/packages/civicrm-civicrm-core)[internal/dload

Downloads binaries.

98142.7k10](/packages/internal-dload)

PHPackages © 2026

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