PHPackages                             makomweb/tactix - 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. makomweb/tactix

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

makomweb/tactix
===============

Tooling for tactical domain driven design

v0.1.7(2mo ago)0165↓92.9%[1 issues](https://github.com/makomweb/tactix/issues)MITPHPPHP ^8.2CI passing

Since Jan 14Pushed 1mo agoCompare

[ Source](https://github.com/makomweb/tactix)[ Packagist](https://packagist.org/packages/makomweb/tactix)[ RSS](/packages/makomweb-tactix/feed)WikiDiscussions master Synced yesterday

READMEChangelog (8)Dependencies (22)Versions (11)Used By (0)

Tactix
======

[](#tactix)

[![app-ci-workflow](https://github.com/makomweb/tactix/actions/workflows/app-ci.yaml/badge.svg)](https://github.com/makomweb/tactix/actions/workflows/app-ci.yaml/badge.svg)[![codecov](https://camo.githubusercontent.com/2c81e46dc6628926c1098692f6036c15526f598f1550a8faeab46a72896c4e16/68747470733a2f2f636f6465636f762e696f2f6769746875622f6d616b6f6d7765622f7461637469782f67726170682f62616467652e7376673f746f6b656e3d4c424442554357503641)](https://codecov.io/github/makomweb/tactix)

Tactical DDD, simplified for PHP. Tag your classes via PHP attributes and analyze forbidden relations.

 [![project-logo](./assets/logo.png)](./assets/logo.png)

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

[](#architecture)

```
┌─────────────────────────────────┐
│    Project Source Code          │
│    (tagged PHP classes)         │
└────────────────┬────────────────┘
                 │
                 ▼
┌─────────────────────────────────┐
│    Analyzer Layer               │
│    (PhpFileAnalyzer, AST)       │
└────────────────┬────────────────┘
                 │
         ┌───────┴────────┐
         ▼                ▼
┌──────────────┐  ┌──────────────────┐
│   Relation   │  │  Rule Engine     │
│   Extractor  │◄─┤  (Blacklist)     │
│ (Violations) │  │  (YAML/DI)       │
└──────┬───────┘  └──────────────────┘
       │
       ▼
┌──────────────────────────────────┐
│       Check API                  │
│  • Check::className()            │
│  • Check::folder()               │
│    (throws on violations)        │
└────────────┬─────────────────────┘
             │
     ┌───────┼────────┐
     ▼       ▼        ▼
┌─────────┐ ┌──────┐ ┌──────────┐
│   CLI   │ │ HTML │ │Framework │
│ Command │ │Report│ │ Bundles  │
└─────────┘ └──────┘ └──────────┘

```

Flow: Tagged source code → AST analysis → Rule validation → Check API → Output (CLI/Report/Framework)

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

[](#installation)

```
composer require --dev makomweb/tactix
```

Requirements:

- PHP ^8.2
- your source code being tagged with [PHP Molecules](https://github.com/xmolecules/phpmolecules)

Usage
-----

[](#usage)

### 1. Tag your classes

[](#1-tag-your-classes)

- install the tags package from PHP Molecules as a regular dependency via:

```
composer require xmolecules/phpmolecules
```

- tag your classes with the available attributes:

```
use PHPMolecules\DDD\Attribute\AggregateRoot;
use PHPMolecules\DDD\Attribute\Entity;
use PHPMolecules\DDD\Attribute\ValueObject;
use PHPMolecules\DDD\Attribute\Service;
use PHPMolecules\DDD\Attribute\Factory;
use PHPMolecules\DDD\Attribute\Repository;

#[Entity]
final class User {}
```

### 2. Either Check your classes or folders manually

[](#2-either-check-your-classes-or-folders-manually)

```
use Tactix\Blacklist;
use Tactix\Check;
use Tactix\YieldViolations;

$check = new Check(new YieldViolations(new Blacklist(Blacklist::DEFAULT_DATA)));
$check->className(User::class);

// or:
$check->folder(__DIR__.'/src');
```

`Check` throws on violations:

- `Tactix\ClassViolationException`
- `Tactix\FolderViolationException`

Both exceptions contain a `$violations` property of type `array` to get further details about whether there are missing tags, ambiguity or forbidden relations.

```
(MyValueObject)-[consumes]->(MyEntity) is a forbidden relation! ❌

```

### 3. Or generate a report for a specific folder

[](#3-or-generate-a-report-for-a-specific-folder)

Tactix provides a Symfony Console command `tactix:report` that creates a static HTML report for a source folder.

```
# Run the report command for a folder.
bin/console tactix:report
# or, when installed as a dependency with optional output directory
vendor/bin/console tactix:report  --out-dir=
# Exclude specific namespaces from the report (can be used multiple times)
vendor/bin/console tactix:report  --exclude-namespace="App\\CLI\\" --exclude-namespace="App\\Infrastructure\\"
```

Options:

- `--out-dir`: Base output directory for reports (defaults to project root)
- `--exclude-namespace`: Namespace prefix to exclude from the report (can be used multiple times). By default, `Doctrine\\`, `Symfony\\`, and `Psr\\` namespaces are excluded. When you provide your own exclusions, you replace these defaults.

Notes:

- the output files index.html, report.js, chart.js, styles.css are created
- the command prints discovered classes and forbidden relations and finishes with `Report written to: ./report/index.html`.

Framework Integration
---------------------

[](#framework-integration)

Tactix is framework-agnostic. The core package does not depend on any specific full-stack framework and can be integrated into different environments.

### Symfony

[](#symfony)

Tactix provides a Symfony Bundle that automatically configures the `tactix:report` command and provides a `Blacklist` service via dependency injection.

#### 1. Register the Bundle

[](#1-register-the-bundle)

The bundle is auto-discovered via Symfony Flex. If you're not using Flex or need manual registration:

```
// config/bundles.php
return [
    // ...
    Tactix\TactixBundle::class => ['all' => true],
];
```

#### 2. Configure Blacklist Rules

[](#2-configure-blacklist-rules)

Create `config/packages/tactix.yaml`:

```
tactix:
  blacklist:
    Entity:
      - Factory
      - Service
      - AggregateRoot
    ValueObject:
      - Entity
      - AggregateRoot
      - Repository
      - Factory
      - Service
    AggregateRoot:
      - Factory
    Repository:
      - Factory
      - Service
    Factory:
      - Repository
    Service: []
```

Or inherit from defaults by creating an empty config (uses `Blacklist::DEFAULT_DATA`):

```
tactix: ~
```

#### 3. Use in Your Application

[](#3-use-in-your-application)

The `Blacklist` service is automatically available via dependency injection:

```
use Tactix\Blacklist;
use Tactix\YieldViolations;

final class MyArchitectureValidator
{
    public function __construct(private Blacklist $blacklist) {}

    public function validateFolder(string $folder): void
    {
        $violations = new YieldViolations($this->blacklist);
        $results = iterator_to_array($violations->fromFolder($folder));

        if (!empty($results)) {
            throw new \RuntimeException('Architecture violations found!');
        }
    }
}
```

Or create a `Check` instance for convenient validation:

```
$check = new Check(new YieldViolations($this->blacklist));
$check->className(MyClass::class);  // throws on violation
```

### Laravel

[](#laravel)

Tactix can be integrated into Laravel projects with a custom service provider.

#### 1. Create a Service Provider

[](#1-create-a-service-provider)

```
