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
=================

DDD Kernel for PHP — BoundedContext, ContextResponse, DomainResponse, DomainKernel

v1.0.0(3w ago)0110↓82.1%1MITPHPPHP &gt;=8.2CI passing

Since Jun 1Pushed 2w agoCompare

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

READMEChangelog (6)Dependencies (13)Versions (3)Used By (1)

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-3](https://camo.githubusercontent.com/8ec91610a7e9f5a2cf45a8364134f116ceff76ab77343dfb7f4a190e8b70c66e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5053522d2d332d4c6f676765722d626c75652e737667)](https://www.php-fig.org/psr/psr-3/)[![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 part of the open-source foundation that generated code runs on.

The DDD kernel you always wanted. Eight files. Zero magic. Full control.

---

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

[](#why-jardis-kernel)

Most DDD frameworks force you into their world. Jardis Kernel gives you the hexagonal building blocks for Domain-Driven Design in PHP — DomainApp, BoundedContext, ConnectionPool — and stays out of the way.

- **`new DomainApp()` — done.** No configuration, no YAML, no service files. Your domain boots itself.
- **Plain PDO works.** Pass a PDO, get going. Need connection pooling later? Swap in a ConnectionPool. Same API.
- **Services shared across domains automatically.** Five domains, one database connection. First-write-wins. Zero plumbing.
- **Every service is optional.** Need a cache? Override one method. Don't need one? Don't touch anything.
- **ClassVersion built in.** Versioned classes via namespace injection — the foundation for Jardis-generated code.
- **Immutable kernel.** Once built, nothing changes. Safe for application servers, workers, long-running processes.

---

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

[](#installation)

```
composer require jardiscore/kernel
```

---

Quickstart
----------

[](#quickstart)

### 1. Create your Domain

[](#1-create-your-domain)

```
use JardisCore\Kernel\DomainApp;

class Ecommerce extends DomainApp
{
    public function order(): OrderContext
    {
        return new OrderContext($this->kernel());
    }
}
```

### 2. Define a Bounded Context

[](#2-define-a-bounded-context)

```
use JardisCore\Kernel\BoundedContext;
use JardisCore\Kernel\Response\DomainResponse;
use JardisCore\Kernel\Response\DomainResponseTransformer;

class PlaceOrder extends BoundedContext
{
    public function __invoke(): DomainResponse
    {
        $order = $this->payload();
        $pdo = $this->resource()->dbConnection();

        $stmt = $pdo->prepare('INSERT INTO orders (customer, total) VALUES (?, ?)');
        $stmt->execute([$order['customer'], $order['total']]);

        $this->result()->addData('orderId', (int) $pdo->lastInsertId());
        $this->result()->addEvent(new OrderPlaced($order));

        return (new DomainResponseTransformer())->transform($this->result());
    }
}

final class OrderPlaced
{
    public function __construct(public readonly array $order)
    {
    }
}
```

The context class is the API boundary — it wires named use-case methods to their handlers via `context()`, which sets the payload for the call chain:

```
class OrderContext extends BoundedContext
{
    public function placeOrder(array $order): DomainResponse
    {
        return $this->context(PlaceOrder::class, $order)();
    }
}
```

### 3. Use it

[](#3-use-it)

```
$shop = new Ecommerce();
$response = $shop->order()->placeOrder(['customer' => 'Acme', 'total' => 99.90]);

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

That's it. No bootstrap file. No container setup. No framework.

---

Provide a Database
------------------

[](#provide-a-database)

The simplest way — a plain PDO:

```
class Ecommerce extends DomainApp
{
    protected function dbConnection(): ConnectionPoolInterface|PDO|false|null
    {
        return new PDO('mysql:host=localhost;dbname=shop', 'root', '');
    }
}
```

That's all you need. A PDO. Works everywhere.

---

Provide Services
----------------

[](#provide-services)

Override protected methods to add infrastructure. Every method uses three-state logic:

ReturnMeaning**object**Use this service. Share it with other DomainApps (first-write-wins).**null**No local service. Use the shared one from another DomainApp if available.**false**Explicitly disabled. Don't use shared fallback either.```
class Ecommerce extends DomainApp
{
    protected function dbConnection(): ConnectionPoolInterface|PDO|false|null
    {
        return new PDO('mysql:host=localhost;dbname=shop', 'root', '');
    }

    protected function logger(): LoggerInterface|false|null
    {
        return new MyLogger('/var/log/shop.log');
    }

    protected function classVersionConfig(): ClassVersionConfig
    {
        return new ClassVersionConfig(
            version: ['v1' => ['v1'], 'v2' => ['v2', 'current']],
            fallbacks: ['v2' => ['v1']],
        );
    }
}
```

---

Multi-Domain Service Sharing
----------------------------

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

Multiple domains in one application share services automatically:

```
$ecommerce = new Ecommerce();   // Builds PDO, registers it shared
$billing   = new Billing();     // Gets the same PDO — zero config
$analytics = new Analytics();   // Same. First-write-wins.
```

A domain that needs its own connection? Override the method. A domain that wants no connection at all? Return `false`.

---

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

[](#advanced-connectionpool-optional)

For application servers and read replicas, install `jardisadapter/dbconnection` and use ConnectionPool instead of plain PDO:

```
composer require jardisadapter/dbconnection
```

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

class Ecommerce extends DomainApp
{
    protected function dbConnection(): ConnectionPoolInterface|PDO|false|null
    {
        $factory = new ConnectionFactory();

        return 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. The rest of your code doesn't change.

---

Direct Kernel Usage
-------------------

[](#direct-kernel-usage)

For full control without DomainApp, use DomainKernel directly:

```
use JardisCore\Kernel\DomainKernel;

$kernel = new DomainKernel(
    domainRoot: __DIR__ . '/src',
    connection: new PDO('mysql:host=localhost;dbname=shop', 'root', ''),
    logger: $myLogger,
    env: ['app_env' => 'production'],
);

$kernel->env('APP_ENV');     // 'production' (case-insensitive)
$kernel->dbConnection();     // PDO instance
$kernel->container();        // Factory (always available)
```

---

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

[](#architecture)

```
DomainApp                       Entry point. Lazy bootstrap. Service sharing.
    ├── domainRoot()            Auto-detected via Reflection
    ├── classVersion()          Built from classVersionConfig()
    ├── cache()                 Three-state: object | null | false
    ├── logger()                   ↓
    ├── eventDispatcher()          ↓
    ├── httpClient()               ↓
    ├── dbConnection()             ↓
    ├── mailer()                   ↓
    ├── filesystem()               ↓
    ├── factory()               Factory + ClassVersion + DI Container
    └── loadEnv()               domainRoot/.env → private ENV

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

BoundedContext                  Use case handler.
    ├── handle(class, ...args)  Pass-through. Inherits caller's payload+version.
    ├── context(class, $p, $v)  Fresh context. Sets payload+version explicitly.
    │                           Used at API boundaries to start a new call chain.
    ├── resource()              Access to DomainKernel
    ├── payload()               Request data
    ├── version()               Active class-resolution version
    └── result()                Lazy ContextResponse

ContextResponse → DomainResponseTransformer → DomainResponse
    Mutable accumulator    Recursive aggregation    Immutable answer

```

---

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

[](#related-packages)

**Included dependencies:**

PackagePurpose`jardissupport/contract`Interface contracts (DomainKernelInterface, etc.)`jardissupport/classversion`Versioned class resolution via namespace injection`jardissupport/factory`PSR-11 Container + class instantiation`jardissupport/dotenv`ENV file loading**Optional (composer suggest):**

PackagePurpose`jardisadapter/dbconnection`ConnectionPool with read/write splitting, health checks, load balancing---

Kernel and Foundation
---------------------

[](#kernel-and-foundation)

Jardis Kernel is the **DDD core** — it provides the building blocks but leaves service assembly to you. Its sister package **[Jardis Foundation](https://github.com/jardisCore/foundation)** (`jardiscore/foundation`) builds on top of Kernel and turns it into a ready-to-run platform:

KernelFoundation**Approach**Override protected methods, wire services yourselfEverything configured via `.env`**Entry point**`class MyApp extends DomainApp``class MyApp extends JardisApp`**Services**You build themAuto-assembled from ENV variables**Dependencies**Minimal (4 packages + PSR interfaces)Full Jardis ecosystem (Cache, Logger, DbConnection, EventDispatcher, HTTP)**Use case**Custom setups, libraries, testingProduction DDD projects**When to use which:** Start with Foundation for most projects — it handles all infrastructure wiring. Use Kernel directly when you need full control or want to integrate Jardis into an existing DI setup.

### Runtime for Jardis-generated code

[](#runtime-for-jardis-generated-code)

Both Kernel and Foundation serve as the **runtime** for the code Jardis generates — DDD project structures like Aggregates, BoundedContexts, Repositories, Commands, and Queries that run directly on these packages:

```
Jardis (development-time)
    │
    │  generates
    ▼
DDD Project Code (Aggregates, BoundedContexts, Repositories, ...)
    │
    │  runs on
    ▼
Foundation (JardisApp)  ──extends──▶  Kernel (DomainApp)
    ENV-driven                        Manual wiring
    Production-ready                  Full control

```

ClassVersion — built into the Kernel — is the foundation for versioned class resolution in Jardis-generated code. It enables namespace-based class versioning so generated code can evolve without breaking existing consumers.

---

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 90% of packages

Maintenance96

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 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

27d 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 (11 commits)")

---

Tags

bounded-contextcode-generationcqrsddddomain-driven-designhexagonal-architecturejardisphpkernelddddomainHeadgentbounded-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.4k86.9M2.2k](/packages/symfony-symfony)[cakephp/cakephp

The CakePHP framework

8.8k19.1M1.7k](/packages/cakephp-cakephp)[laravel/framework

The Laravel Framework.

34.8k532.1M19.4k](/packages/laravel-framework)[tempest/framework

The PHP framework that gets out of your way.

2.2k31.1k12](/packages/tempest-framework)[drupal/core-recommended

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

6941.5M396](/packages/drupal-core-recommended)[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)
