PHPackages                             tsars/ddd-generator - 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. [CLI &amp; Console](/categories/cli)
4. /
5. tsars/ddd-generator

ActiveProject[CLI &amp; Console](/categories/cli)

tsars/ddd-generator
===================

CLI tool to generate DDD structure: bounded contexts, aggregates, entities, VOs, events, commands, queries and tests

1.0.9(3mo ago)18MITPHPPHP ^8.0

Since Apr 9Pushed 3mo agoCompare

[ Source](https://github.com/TsarS/ddd-generator)[ Packagist](https://packagist.org/packages/tsars/ddd-generator)[ RSS](/packages/tsars-ddd-generator/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (1)Versions (8)Used By (0)

PHP DDD Generator
=================

[](#php-ddd-generator)

CLI tool to generate DDD structure: bounded contexts, aggregates, entities, VOs, events, commands, queries, listeners, and tests.

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

[](#installation)

```
composer global require tsars/ddd-generator
```

Or clone the repository and install dependencies:

```
git clone https://github.com/TsarS/ddd-generator.git
cd ddd-generator
composer install
```

Usage
-----

[](#usage)

### Basic usage

[](#basic-usage)

```
php ddd create  --config=/path/to/ddd.json --events=/path/to/events.json
```

### Example

[](#example)

```
php ddd create myproject --config=./ddd.json --events=./events.json
```

Configuration Files
-------------------

[](#configuration-files)

### ddd.json - Main Configuration

[](#dddjson---main-configuration)

```
{
  "appName": "myproject",
  "aggregates": [
    {
      "name": "Product",
      "isAggregate": true,
      "properties": [
        {"name": "name", "type": "string", "validations": ["notEmpty"]},
        {"name": "description", "type": "string", "nullable": true},
        {"name": "category", "type": "Category", "isVO": true, "nullable": true}
      ],
      "events": ["Created", "Renamed", "Deleted", "Archived", "Reinstated"],
      "commands": ["Create", "Archive", "Delete", "Reinstate", "Rename"],
      "queries": ["GetAll", "GetById", "GetByName", "Unique"]
    }
  ]
}
```

#### Aggregate Fields:

[](#aggregate-fields)

FieldTypeDescription`name`stringAggregate/entity name`isAggregate`boolIf `true` - generates Aggregate with status, archive, delete. If `false` - simple Entity`properties`arrayList of entity properties`properties[].name`stringProperty name`properties[].type`stringPHP type (string, int, etc.) or VO name`properties[].nullable`boolCan be null`properties[].isVO`boolIs this type a Value Object`properties[].validations`arrayList of validations (not yet implemented)`events`arrayList of domain events`commands`arrayList of commands (Create, Archive, etc.)`queries`arrayList of queries (GetAll, GetById, etc.)### events.json - Inter-Aggregate Links

[](#eventsjson---inter-aggregate-links)

```
{
  "subscribers": [
    {
      "source": "Product",
      "event": "Created",
      "target": "Category",
      "description": "When Product is created, update Category stats"
    }
  ]
}
```

#### Subscriber Fields:

[](#subscriber-fields)

FieldTypeDescription`source`stringSource aggregate name`event`stringEvent name (Created, Archived, etc.)`target`stringTarget aggregate name where adapter will be created`description`stringLink description (optional)Generated Structure
-------------------

[](#generated-structure)

For each aggregate:

```
src//
├── Domain/
│   ├── Entity/
│   │   ├── .php          # Main entity
│   │   ├── Aggregate.php                 # Base Aggregate class (if isAggregate=true)
│   │   └── EventTrait.php                # Event trait
│   ├── VO/
│   │   ├── ID.php                        # Value Object ID
│   │   ├── Status.php                    # Status VO
│   │   └── .php                 # Custom VOs
│   ├── Event//
│   │   ├── Created.php
│   │   ├── Archived.php
│   │   └── ...
│   ├── Exception//
│   │   └── EmptyNameException.php
│   └── Repository/
│       └── RepositoryInterface.php
├── Application//
│   ├── Command/
│   │   ├── Create/
│   │   │   ├── CreateCommand.php
│   │   │   └── CreateCommandHandler.php
│   │   ├── Archive/
│   │   └── ...
│   ├── Query/
│   │   ├── GetAll/
│   │   ├── GetById/
│   │   └── ...
│   ├── Listener/
│   │   ├── CreatedListener.php
│   │   └── ...
│   └── Adapter/                          # Inter-aggregate adapters (from events.json)
│       └── ToSubscriber.php
└── Infrastructure/
    ├── API/
    └── Persistance/

```

Configuration Examples
----------------------

[](#configuration-examples)

### Simple Aggregate

[](#simple-aggregate)

```
{
  "name": "User",
  "isAggregate": true,
  "properties": [
    {"name": "firstName", "type": "string"},
    {"name": "lastName", "type": "string"},
    {"name": "email", "type": "string"}
  ],
  "events": ["Created", "Updated", "Deleted"],
  "commands": ["Create", "Update", "Delete"],
  "queries": ["GetById", "GetAll"]
}
```

### Non-Aggregate Entity with Value Objects

[](#non-aggregate-entity-with-value-objects)

```
{
  "name": "Address",
  "isAggregate": false,
  "properties": [
    {"name": "street", "type": "string"},
    {"name": "city", "type": "City", "isVO": true},
    {"name": "zipCode", "type": "string"}
  ],
  "events": ["Created"],
  "commands": ["Create"],
  "queries": ["GetAll"]
}
```

In this example, `City` will be generated as a Value Object in `Domain/VO/City.php`, not as a separate entity.

### With Events and Inter-Aggregate Links

[](#with-events-and-inter-aggregate-links)

**ddd.json:**

```
{
  "appName": "shop",
  "aggregates": [
    {
      "name": "Order",
      "isAggregate": true,
      "properties": [
        {"name": "customerId", "type": "string"},
        {"name": "totalAmount", "type": "Money", "isVO": true}
      ],
      "events": ["Created", "Cancelled", "Completed"],
      "commands": ["Create", "Cancel", "Complete"],
      "queries": ["GetById", "GetAll", "GetByCustomer"]
    },
    {
      "name": "Invoice",
      "isAggregate": true,
      "properties": [
        {"name": "amount", "type": "Money", "isVO": true},
        {"name": "status", "type": "InvoiceStatus", "isVO": true}
      ],
      "events": ["Generated", "Paid"],
      "commands": ["Generate", "MarkPaid"],
      "queries": ["GetByOrder"]
    }
  ]
}
```

**events.json:**

```
{
  "subscribers": [
    {
      "source": "Order",
      "event": "Completed",
      "target": "Invoice",
      "description": "Generate invoice when order is completed"
    },
    {
      "source": "Order",
      "event": "Cancelled",
      "target": "Invoice",
      "description": "Cancel invoice when order is cancelled"
    }
  ]
}
```

Generated Files
---------------

[](#generated-files)

### Entity (Aggregate)

[](#entity-aggregate)

```
class Product extends Aggregate
{
    use EventTrait;

    private ID $id;
    private Status $status;
    private DateTimeImmutable $createdAt;
    private string $name;

    // Constructor, factory method, getters...

    public function archive(): void { ... }
    public function delete(): void { ... }
    public function rename(string $newName): void { ... }
}
```

### Event Subscriber (Adapter)

[](#event-subscriber-adapter)

```
class CreatedProductToCategorySubscriber
{
    public function handle(ProductCreated $event): void
    {
        // TODO: Implement logic to react to ProductCreated
        // Create or update related Category entity
    }
}
```

Tests
-----

[](#tests)

For each aggregate, basic tests are generated in `tests//`:

- `Domain/Entity/Test.php`
- `Domain/Event/Test.php`
- `Application/Command//CommandHandlerTest.php`
- `Application/Query//QueryHandlerTest.php`
- `Domain/Repository/RepositoryTest.php`

Development
-----------

[](#development)

### Project Structure

[](#project-structure)

```
ddd-generator/
├── src/
│   ├── DDDGenerator.php          # Main generator
│   └── Command/
│       └── CreateAppCommand.php  # CLI command
├── templates/                    # Templates for generation
│   ├── *.php.template
│   ├── test/
│   │   └── *.php.template
│   └── config/
│       ├── ddd.json
│       └── events.json
├── ddd.php                      # Entry point
└── composer.json

```

### Run Tests

[](#run-tests)

```
composer test
# or
./vendor/bin/phpunit
```

License
-------

[](#license)

MIT

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance80

Actively maintained with recent releases

Popularity6

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity44

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

Every ~0 days

Total

7

Last Release

106d ago

### Community

Maintainers

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

---

Top Contributors

[![medframework](https://avatars.githubusercontent.com/u/58857349?v=4)](https://github.com/medframework "medframework (14 commits)")

### Embed Badge

![Health badge](/badges/tsars-ddd-generator/health.svg)

```
[![Health](https://phpackages.com/badges/tsars-ddd-generator/health.svg)](https://phpackages.com/packages/tsars-ddd-generator)
```

PHPackages © 2026

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