PHPackages                             jardiscore/kernel - 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. [Framework](/categories/framework)
4. /
5. jardiscore/kernel

ActiveLibrary[Framework](/categories/framework)

jardiscore/kernel
=================

Infrastructure kernel for PHP — an immutable DomainKernel holding wired-up cache, logger, event dispatcher, HTTP client, database, mailer and filesystem, plus an optional ENV-driven bootstrap. Jardis-generated domain code reaches it through a single interface.

v1.0.1(3w ago)05↓72.4%[2 PRs](https://github.com/jardisCore/kernel/pulls)2MITPHPPHP &gt;=8.2CI passing

Since Jul 21Pushed 1w agoCompare

[ Source](https://github.com/jardisCore/kernel)[ Packagist](https://packagist.org/packages/jardiscore/kernel)[ Docs](https://jardis.io)[ RSS](/packages/jardiscore-kernel/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (6)Dependencies (46)Versions (8)Used By (2)

Jardis Kernel
=============

[](#jardis-kernel)

[![Build Status](https://github.com/jardisCore/kernel/actions/workflows/ci.yml/badge.svg)](https://github.com/jardisCore/kernel/actions/workflows/ci.yml/badge.svg)[![Latest Version](https://camo.githubusercontent.com/6a4c978db32f9591c6f110cf55cab264ce60b07ecf5e40eb9aeee595bae7c9f0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6a6172646973636f72652f6b65726e656c2e737667)](https://packagist.org/packages/jardiscore/kernel)[![License: MIT](https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667)](LICENSE.md)[![PHP Version](https://camo.githubusercontent.com/a68b290dcc313d698dc138a1111aa83eee2f143605449d7e8b5416ea6f88558f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d253345253344382e322d3737374242342e737667)](https://www.php.net/)[![PHPStan Level](https://camo.githubusercontent.com/c51bda247654363d3e30bc352674dd761a9557803a14af0226eb411d6dc0006b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d4c6576656c253230382d627269676874677265656e2e737667)](phpstan.neon)[![PSR-12](https://camo.githubusercontent.com/34b10db0caa29bacd49bda5c437a8de95385f036f3230b31fa605326e18da22c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436f64652532305374796c652d5053522d2d31322d626c75652e737667)](phpcs.xml)[![Coverage](https://camo.githubusercontent.com/6188a20e6d118eb165417785b0f896fbc811d689eac6f46cd8a7900add2c7bbd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436f7665726167652d39312532352d627269676874677265656e2e737667)](https://github.com/jardisCore/kernel)[![PSR-11](https://camo.githubusercontent.com/98be7eb7e57be670e94d2f798114804c0fa75a3c0435e17de37bee92cc966864/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5053522d2d31312d436f6e7461696e65722d626c75652e737667)](https://www.php-fig.org/psr/psr-11/)[![PSR-14](https://camo.githubusercontent.com/ad320513b35a33c8e1b26659280cd1bdf4bbd3dbceabfdec8debaff5bea52295/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5053522d2d31342d4576656e74253230446973706174636865722d626c75652e737667)](https://www.php-fig.org/psr/psr-14/)[![PSR-16](https://camo.githubusercontent.com/19b80673b3dc8065ce5caacac68f56ef79c8ed809ba2c017a36c6bb3ff37e039/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5053522d2d31362d53696d706c6525323043616368652d626c75652e737667)](https://www.php-fig.org/psr/psr-16/)[![PSR-18](https://camo.githubusercontent.com/07f2407c14b606d22023b8c5e970a3afd744e71d1b5b367df2cd29372c7ec9cb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5053522d2d31382d48545450253230436c69656e742d626c75652e737667)](https://www.php-fig.org/psr/psr-18/)

> Part of **[Jardis](https://jardis.io)** — the Domain-Driven Design platform for PHP. You model your domain; Jardis generates the production-ready hexagonal code (DTOs, Command/Query handlers, repositories, persistence). This package is the runtime the generated code runs on.

**The Application-side offer for Jardis-generated domains.** One immutable infrastructure holder (`DomainKernel`, the "Koffer") plus an optional ENV-driven packer (`BuildDomainKernelFromEnv`) — you inject the kernel into the generated domain facade's constructor, nothing more.

---

Why Jardis Kernel?
------------------

[](#why-jardis-kernel)

Generated Jardis domains are hexagonal all the way down: they depend only on `jardissupport/contracts` interfaces, never on a concrete implementation. This package is one way to satisfy those interfaces at runtime — a minimal, adapter-agnostic infrastructure bundle.

- **`DomainKernelInterface` in, done.** Every generated `{Domain}Context` and BC facade takes the Koffer via constructor injection — nothing else to wire.
- **Plain PDO works.** Pass a PDO, get going. Need connection pooling later? Swap in a ConnectionPool. Same `dbConnection()` accessor.
- **Every service is optional.** Nullable by design — a Koffer without a logger is a perfectly valid Koffer; the domain checks and acts accordingly.
- **ClassVersion built in.** Versioned classes via namespace injection is a Support-package concern (`jardissupport/classversion`); the Koffer just carries a container that resolves it.
- **Immutable kernel.** Once built, nothing changes. Safe for application servers, workers, long-running processes.
- **ENV wiring is optional, not assumed.** `BuildDomainKernelFromEnv` packs a Koffer from cascading `.env` files if you want that; build your own `DomainKernel` directly if you don't.

---

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

[](#installation)

```
composer require jardiscore/kernel
```

---

Quickstart
----------

[](#quickstart)

### 1. Build a Koffer

[](#1-build-a-koffer)

The simplest Koffer — no services at all:

```
use JardisCore\Kernel\DomainKernel;

$kernel = new DomainKernel(domainRoot: __DIR__);
```

A Koffer with a database connection — plain PDO is enough:

```
$kernel = new DomainKernel(
    domainRoot: __DIR__,
    connection: new PDO('mysql:host=localhost;dbname=shop', 'root', ''),
);
```

### 2. Hand it to the generated domain facade

[](#2-hand-it-to-the-generated-domain-facade)

Jardis-generated domains take the Koffer via constructor injection — nothing extends `DomainApp` anymore (Kernel-Entkopplung, see "Constitutional Note" below):

```
$ecommerce = new Ecommerce($kernel);   // {Domain} facade, generated by Jardis
$response = $ecommerce->order()->placeOrder(['customer' => 'Acme', 'total' => 99.90]);

$response->isSuccess();   // true
$response->getData();     // ['PlaceOrder' => ['orderId' => 42]]
$response->getEvents();   // ['PlaceOrder' => [OrderPlaced {...}]]
```

The generated `{Domain}Context` base class (the Naht, `handle()`/`context()`) and the `ContextResponse` → `DomainResponse` response pipeline are themselves part of what Jardis generates per domain — see the `platform-implementation`skill / `docs.jardis.io` for the generated-code contract. This package only provides the Koffer these generated classes consume.

### 3. Or: pack the Koffer from ENV

[](#3-or-pack-the-koffer-from-env)

For projects that want zero manual service wiring, `BuildDomainKernelFromEnv`assembles a Koffer from a cascading `.env` tree (templates: [`docs/env-examples/`](docs/env-examples/)):

```
use JardisCore\Kernel\Bootstrap\BuildDomainKernelFromEnv;

$packer = new BuildDomainKernelFromEnv();
$kernel = $packer(__DIR__ . '/config');   // reads config/.env (+ cascade)

$ecommerce = new Ecommerce($kernel);
```

`BuildDomainKernelFromEnv` wires eight services (cache, logger, event dispatcher + listener registry, HTTP client, DB connection, mailer, filesystem) from `DB_*` / `CACHE_*` / `LOG_*` / `HTTP_*` / `MAIL_*` / `REDIS_*` ENV keys — see [`docs/env-examples/README.md`](docs/env-examples/README.md)for the full key reference. The resulting packed `DomainKernel` exposes eleven accessors in total (the eight services above, plus `domainRoot()`, `env()`, and `container()`, which are not ENV-wired services — see the accessor table below). Every adapter it can use (`jardisadapter/cache`, `jardisadapter/dbconnection`, `jardisadapter/eventdispatcher`, `jardisadapter/filesystem`, `jardisadapter/http`, `jardisadapter/logger`, `jardisadapter/mailer`) is a composer `suggest` — not installed, or not configured, means that accessor stays `null` on the packed Koffer. Nothing throws for a missing optional service.

---

DomainKernel — the Koffer
-------------------------

[](#domainkernel--the-koffer)

```
$kernel = new DomainKernel(
    domainRoot: '/path/to/config',      // required
    container: $factory,                // ?ContainerInterface
    cache: $cache,                      // ?CacheInterface
    logger: $logger,                    // ?LoggerInterface
    eventDispatcher: $dispatcher,       // ?EventDispatcherInterface
    eventListenerRegistry: $registry,   // ?EventListenerRegistryInterface
    httpClient: $client,                // ?ClientInterface
    connection: $pool,                  // ConnectionPoolInterface|PDO|null
    mailer: $mailer,                    // ?MailerInterface
    filesystem: $filesystemService,     // ?FilesystemServiceInterface
    env: ['db_host' => 'localhost'],    // array — private ENV, takes precedence over $_ENV
);
```

MethodReturn`domainRoot()``string``env(string $key)``mixed` — case-insensitive; private ENV &gt; `$_ENV``container()``Factory` — always wraps the injected container`cache()``?CacheInterface``logger()``?LoggerInterface``eventDispatcher()``?EventDispatcherInterface``eventListenerRegistry()``?EventListenerRegistryInterface` — paired with `eventDispatcher()`; same underlying provider instance (D3)`httpClient()``?ClientInterface``dbConnection()``ConnectionPoolInterface|PDO|null``mailer()``?MailerInterface``filesystem()``?FilesystemServiceInterface``DomainKernel` builds nothing and reads no ENV itself — it is a pure, immutable consumer. All ENV/service-assembly is `Bootstrap\BuildDomainKernelFromEnv`'s job (or your own equivalent).

`eventListenerRegistry()` exists so a generated `{Agg}EventRouter` can register itself on the domain facade's constructor without any Application wiring: a fresh build carries new routers automatically. Without a registry in the Koffer, event routing simply stays inactive — no error.

---

Multi-Domain Service Sharing (explicit)
---------------------------------------

[](#multi-domain-service-sharing-explicit)

There is no static registry anymore (Kernel-Entkopplung removed the first-write-wins `ServiceRegistry`, G11) — sharing services across domains is now an explicit choice, not implicit global state:

```
$kernel = (new BuildDomainKernelFromEnv())(__DIR__ . '/config');

$ecommerce = new Ecommerce($kernel);   // same Koffer instance
$billing   = new Billing($kernel);     // same Koffer instance -> same connection, cache, ...
```

A domain that needs its own services builds its own Koffer instead of sharing one:

```
$billingKernel = (new BuildDomainKernelFromEnv())(__DIR__ . '/config-billing');
$billing = new Billing($billingKernel);
```

---

Advanced: ConnectionPool (optional)
-----------------------------------

[](#advanced-connectionpool-optional)

For application servers and read replicas, install `jardisadapter/dbconnection`and pass a `ConnectionPool` instead of plain PDO — either directly, or let `BuildDomainKernelFromEnv` build one from `DB_READER{N}_HOST` ENV keys (see [`docs/env-examples/.env.database.example`](docs/env-examples/.env.database.example)):

```
use JardisAdapter\DbConnection\ConnectionPool;
use JardisAdapter\DbConnection\Factory\ConnectionFactory;

$factory = new ConnectionFactory();

$kernel = new DomainKernel(
    domainRoot: __DIR__,
    connection: new ConnectionPool(
        writer: $factory->mysql('primary', 'user', 'pass', 'shop'),
        readers: [
            $factory->mysql('replica1', 'user', 'pass', 'shop'),
            $factory->mysql('replica2', 'user', 'pass', 'shop'),
        ],
    ),
);
```

`ConnectionPool` provides lifecycle management, health checks, round-robin load balancing, and automatic writer fallback when no readers are available. Everything downstream (`$kernel->dbConnection()`) doesn't change.

---

Architecture
------------

[](#architecture)

```
BuildDomainKernelFromEnv        Bootstrap-Packer (optional). ENV -> Koffer.
    ├── Handler\BuildConnectionFromEnv            mysql | pgsql | sqlite (+ pool)
    ├── Handler\BuildRedisFromEnv                 shared fan-out (-> cache + logger)
    ├── Handler\ExtractPdoFromConnection           feeds the cache "db" layer
    ├── Handler\BuildCacheFromEnv                  memory | apcu | redis | db
    ├── Handler\BuildLoggerFromEnv                 file | console | slack | ... (+redis)
    ├── Handler\BuildEventListenerProviderFromEnv  shared provider (D3)
    ├── Handler\BuildEventDispatcherFromProvider   wraps the same provider
    ├── Handler\BuildHttpClientFromEnv
    ├── Handler\BuildMailerFromEnv
    ├── Handler\BuildFilesystemFromEnv
    ├── Data\CacheLayer                            memory | apcu | redis | db (4 cases)
    └── Data\LogHandler                            file | console | errorlog | syslog |
                                                     browserconsole | redis | slack | teams |
                                                     loki | webhook | null (11 cases)

DomainKernel                    Immutable. Constructor injection only.
    ├── env(key)                Case-insensitive. Private > $_ENV
    ├── container()             Always Factory. Wraps external container.
    ├── cache()                 ?CacheInterface
    ├── logger()                ?LoggerInterface
    ├── eventDispatcher()       ?EventDispatcherInterface
    ├── eventListenerRegistry() ?EventListenerRegistryInterface (paired with eventDispatcher, D3)
    ├── httpClient()            ?ClientInterface
    ├── dbConnection()          ConnectionPoolInterface | PDO | null
    ├── mailer()                ?MailerInterface
    └── filesystem()            ?FilesystemServiceInterface

```

Everything downstream of the Koffer — the generated `{Domain}Context` Naht (`handle()`/`context()`), `resource()`/`payload()`/`version()`/`result()`, and the `ContextResponse` → `DomainResponseTransformer` → `DomainResponse`pipeline — is generated per domain by Jardis itself (Kernel-Entkopplung: the generated domain is JardisCore-free; it imports only `jardissupport/contracts`). See the `platform-implementation` skill for that generated-code contract.

---

Constitutional Note (Kernel-Entkopplung D4)
-------------------------------------------

[](#constitutional-note-kernel-entkopplung-d4)

As of the Kernel-Entkopplung redesign, `jardiscore/kernel` sits **outside** the hexagonal inner rings — it is Application-layer, not Domain-layer. Concretely:

- The Koffer core (`DomainKernel` + the contract interfaces it implements) stays adapter-free: only `jardissupport/contracts` + PSR interfaces.
- The `Bootstrap\` sub-namespace legitimately imports concrete adapter packages (`jardisadapter/*`) — that is Application wiring, not Domain code, and Application code is allowed to depend on concrete infrastructure.
- Generated Jardis domains never import anything under `Bootstrap\` — they only ever see `DomainKernelInterface`.

This mirrors the project-wide rule ("Composition over Inheritance", flat extends only inside generated code) applied one layer up: the Application composes the Koffer from adapters; the Domain composes its behaviour from the Koffer.

---

Related Packages
----------------

[](#related-packages)

**Included dependencies:**

PackagePurpose`jardissupport/contracts`Interface contracts (`DomainKernelInterface`, `EventListenerRegistryInterface`, etc.)`jardissupport/classversion`Versioned class resolution via namespace injection`jardissupport/factory`PSR-11 Container + class instantiation`jardissupport/dotenv`Cascading `.env` loading — used by `BuildDomainKernelFromEnv`**Optional (composer suggest, used by `Bootstrap\BuildDomainKernelFromEnv`):**

PackagePurpose`jardisadapter/cache`Multi-layer caching (Memory, APCu, Redis, Database)`jardisadapter/dbconnection`ConnectionPool with read/write splitting, health checks, load balancing`jardisadapter/eventdispatcher`PSR-14 event dispatching + listener registry`jardisadapter/filesystem`Local and S3 filesystem abstraction`jardisadapter/http`PSR-18 HTTP client with handler pipeline`jardisadapter/logger`PSR-3 logger with file/console/network/queue handlers`jardisadapter/mailer`SMTP mailer with STARTTLS, AUTH, HTML/text, attachments---

Documentation
-------------

[](#documentation)

Full documentation, guides, and API reference:

**[docs.jardis.io/en/core/kernel](https://docs.jardis.io/en/core/kernel)**

---

License
-------

[](#license)

Jardis is open source under the [MIT License](LICENSE.md). Free for any purpose — commercial or non-commercial.

---

*Jardis — Development with Passion**Built by [Headgent Development](https://headgent.com)*

AI-Assisted Development
-----------------------

[](#ai-assisted-development)

This package ships with a skill for Claude Code, Cursor, Continue, and Aider. Install it in your consuming project:

```
composer require --dev jardis/dev-skills
```

More details:

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance97

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 75% 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 ~8 days

Total

6

Last Release

22d ago

### Community

Maintainers

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

---

Top Contributors

[![Headgent](https://avatars.githubusercontent.com/u/245725954?v=4)](https://github.com/Headgent "Headgent (3 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

bounded-contextcode-generationcqrsddddomain-driven-designhexagonal-architecturejardisphpphpDomain Driven Designkernelddddomaincode-generationcqrshexagonal-architectureHeadgentbounded-contextjardisCore

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/jardiscore-kernel/health.svg)

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

###  Alternatives

[symfony/symfony

The Symfony PHP framework

31.4k87.4M2.2k](/packages/symfony-symfony)[laravel/framework

The Laravel Framework.

34.9k556.2M21.3k](/packages/laravel-framework)[cakephp/cakephp

The CakePHP framework

8.9k20.0M1.8k](/packages/cakephp-cakephp)[drupal/core-recommended

Locked core dependencies; require this project INSTEAD OF drupal/core.

6943.5M448](/packages/drupal-core-recommended)[tempest/framework

The PHP framework that gets out of your way.

2.3k37.6k20](/packages/tempest-framework)[typo3/cms

TYPO3 CMS is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.

1.2k1.9M122](/packages/typo3-cms)

PHPackages © 2026

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