boundwize/structarmed

Configurable PHP architecture guards — define your layers and rules, then keep them enforced

Maintainers

Package info

github.com/boundwize/structarmed

pkg:composer/boundwize/structarmed

Statistics

Installs: 9

Dependents: 1

Suggesters: 0

Stars: 1

Open Issues: 0

0.0.1 2026-05-08 09:40 UTC

This package is auto-updated.

Last update: 2026-05-08 10:07:48 UTC


README

Image

Latest Version ci build Code Coverage PHPStan Downloads

Configurable PHP architecture guards — define your layers and rules, then keep them enforced.

Installation

composer require --dev boundwize/structarmed

Quick start

vendor/bin/structarmed init

Generates a structarmed.php in your project root. Edit it to match your structure, then run:

vendor/bin/structarmed analyse

If violations are found, the output reports each one:

Image

If everything passes, you get a clean summary:

Image

Configuration

Default

// structarmed.php
use Boundwize\StructArmed\Architecture;
use Boundwize\StructArmed\Preset\Preset;

return Architecture::define()
    ->withPreset(Preset::PSR4());

Multiple presets

->withPresets(Preset::PSR4(), Preset::DDD(), Preset::MVC())

Custom layers and rules

use Boundwize\StructArmed\Architecture;
use Boundwize\StructArmed\Rule\Rules\Layer\MayNotDependOnRule;
use Boundwize\StructArmed\Rule\Rules\Method\MustHaveReturnTypeRule;

return Architecture::define()
    ->layer('Domain', 'src/Domain/')
    ->layer('Application', 'src/Application/')
    ->layer('Infrastructure', 'src/Infrastructure/')
    ->skip([
        'tests/Fixtures/',
        'var/cache/*',
        DddPreset::ENTITY_MUST_BE_FINAL => ['src/Legacy/'],
    ])
    ->rule(
        'domain.must_not_depend_on_infrastructure',
        new MayNotDependOnRule(from: 'Domain', to: 'Infrastructure', toPath: 'Infrastructure')
    )
    ->rule(
        'domain.public_methods_must_have_return_types',
        new MustHaveReturnTypeRule(layer: 'Domain')
    );

Override preset rules

Use rule key constants — never raw strings:

use Boundwize\StructArmed\Preset\Presets\DddPreset;

return Architecture::define()
    ->layer('Domain',         'src/Domain/')
    ->layer('Application',    'src/Application/')
    ->layer('Infrastructure', 'src/Infrastructure/')
    ->withPreset(Preset::DDD())

    // Remove a rule entirely
    ->withoutRule(DddPreset::DOMAIN_NO_BASE_EXCEPTION)

    // Replace a rule with a different configuration
    ->replaceRule(
        DddPreset::ENTITY_MUST_BE_FINAL,
        new MustBeFinalRule(layer: 'Domain', classNamePattern: '/Entity$|Aggregate$/')
    )

    // Add your own custom rule
    ->rule(
        'our.handlers.must_be_in_application',
        new NamingConventionRule(
            classNamePattern: '/Handler$/',
            mustBeInLayer: 'Application'
        )
    );

Preset constructor parameters

->withPreset(Preset::DDD(
    maxComplexity:        3,     // default: 5
    maxMethodLength:      15,    // default: 20
    enforceFinalEntities: false, // default: true
))

->withPreset(Preset::MVC(
    controllerMaxComplexity:   3,  // default: 5
    controllerMaxDependencies: 4,  // default: 5
    viewMaxComplexity:         2,  // default: 3
))

->withPreset(Preset::PSR4(
    sourcePaths: ['src/', 'tests/'], // default: read composer.json PSR-4 paths
))

Available presets

Preset Rules
Preset::PSR4() Verifies configured source paths exist in composer.json autoload or autoload-dev PSR-4 mappings
Preset::DDD() Layer isolation, entity/VO/repository/event/service conventions
Preset::MVC() Layer isolation, thin controllers, model/view/service rules

PHPUnit extension

Run architecture checks as part of your test suite:

<!-- phpunit.xml -->
<extensions>
    <bootstrap class="Boundwize\StructArmed\PHPUnit\StructArmedExtension"/>
</extensions>

Violations cause the test run to fail before any tests execute.

CLI

# Analyse with default config discovery
vendor/bin/structarmed analyse
vendor/bin/structarmed analyze

# Analyse only specific paths
vendor/bin/structarmed analyse src
vendor/bin/structarmed analyze src tests

# Custom config path
vendor/bin/structarmed analyse --config=path/to/structarmed.php
vendor/bin/structarmed analyze --config=path/to/structarmed.php

# JSON output (for CI tools)
vendor/bin/structarmed analyse --report=json
vendor/bin/structarmed analyze --report=json

# Generate initial config
vendor/bin/structarmed init

Layer resolution

Layers are resolved by file path — no attributes needed on classes:

src/Domain/     → 'Domain'
src/Application/ → 'Application'
src/Infrastructure/ → 'Infrastructure'

Rule key constants

Every preset rule has a public constant. Use constants, never raw strings:

// ✅ correct — caught by IDE and static analysis
DddPreset::ENTITY_MUST_BE_FINAL

// ❌ wrong — typo silently does nothing
'ddd.entity.must_be_fnal'

Requirements

  • PHP 8.2 or higher
  • nikic/php-parser ^5.0

License

MIT