spryker / architecture-sniffer
Spryker Architecture Sniffer
Requires
- php: >=8.3
- laminas/laminas-config: ^2.5.1 || ^3.1.0
- laminas/laminas-filter: ^2.5.1
- phpdocumentor/reflection-docblock: ^5.3.0
- phpmd/phpmd: ^2.10.0
- symfony/finder: ^4.0.0 || ^5.0.0 || ^6.0.0
Requires (Dev)
- codeception/codeception: ^5.0.8
- codeception/module-asserts: ^3.0.0
- phpstan/phpstan: ^2.1.0
- spryker/code-sniffer: *
- symfony/var-dumper: ^5.4.24
This package is auto-updated.
Last update: 2026-07-28 13:33:05 UTC
README
Architecture Sniffer for Spryker core, eco-system and applications.
The package ships two independent rulesets. Use the one that matches what you are working on:
| Ruleset | For | Path |
|---|---|---|
| Core | Spryker core, eco-system and module development | vendor/spryker/architecture-sniffer/src/ruleset.xml |
| Project | Application (project) development | vendor/spryker/architecture-sniffer/src/Project/ruleset.xml |
Make sure the sniffer is installed as a require-dev dependency:
composer require --dev spryker/architecture-sniffer
Common to both: lower priorities (higher numbers) always include the higher priorities (lower numbers) — a run at priority 3 also reports 1 and 2.
Spryker Core Development
Use the core ruleset src/ruleset.xml.
Priority Levels
1: API and critical2: Non critical (nice to have)3: Experimental (inspected code needs further fixing)
We use and recommend minimum priority 2 by default for local and CI checks.
Usage
When using Spryker you can use the Spryker CLI console command:
console code:sniff:architecture [-m ModuleName] [optional-sub-path] -v [-p priority]
Verbose output is recommended here.
Or run it manually:
vendor/bin/phpmd src/Pyz/ (xml|text|html) vendor/spryker/architecture-sniffer/src/ruleset.xml --minimumpriority=2
Including the sniffer in PHPStorm
Add a new custom ruleset under Editor -> Inspections -> PHP -> PHP Mess Detector validation and name it Architecture Sniffer.
The ruleset is defined in vendor/spryker/architecture-sniffer/src/ruleset.xml.
Under Framework & Languages -> PHP -> Mess Detector set the path to your phpmd (vendor/bin/phpmd), then run Validate to confirm it works.
Spryker Project Development
Use the project ruleset src/Project/ruleset.xml. It bundles adapted PHPMD, Spryker architecture, and project-only rules.
Priority Levels
1: Critical2: Major3: Medium4: Minor
Recommended minimum priority per project maturity:
1and2: recommended for all projects, including those with legacy code.3: recommended for all new projects.4: recommended for a modern AI-assisted development flow.
Usage
vendor/bin/phpmd src/ (json|text|html) vendor/spryker/architecture-sniffer/src/Project/ruleset.xml --minimumpriority=4
Setup for the project & customizing rules
The project ruleset is meant to be tuned per project. Create a thin project-level phpmd.xml in the project root (PHPMD's conventional default filename) that references the vendor project ruleset, then layer your customizations on top of it — exclude modules, change priorities, or adjust rule properties without touching the vendor package:
<?xml version="1.0"?> <ruleset name="Spryker Project" xmlns="http://pmd.sf.net/ruleset/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <description>Project architecture ruleset.</description> <!-- File / path exclusions (filters WHICH files are analyzed) --> <exclude-pattern>*/Generated/*</exclude-pattern> <exclude-pattern>*/Orm/*</exclude-pattern> <!-- Import the vendor project ruleset (single aggregate reference). To EXCLUDE or OVERRIDE a rule, do it INSIDE this block via <exclude name="..."/>. PHPMD keeps the FIRST copy of a rule it imports by name, so a separate <rule ref> placed after this block is silently ignored — the exclude must live here. --> <rule ref="vendor/spryker/architecture-sniffer/src/Project/ruleset.xml"> <!-- Drop a rule entirely: --> <!-- <exclude name="FacadeSingleFactoryCallRule" /> --> <!-- To OVERRIDE a rule's priority/properties, exclude it here too, then re-add the single rule below: --> <!-- <exclude name="FacadeRule" /> --> <!-- <exclude name="OrmNewEntityNotInCommunicationRule" /> --> </rule> <!-- Change a single rule's priority (lower number = more severe). Requires <exclude name="FacadeRule"/> in the block above. --> <!-- <rule ref="vendor/spryker/architecture-sniffer/src/Project/Zed/ruleset.xml/FacadeRule"> <priority>3</priority> </rule> --> <!-- Pass a property to a rule. Requires <exclude name="OrmNewEntityNotInCommunicationRule"/> above. --> <!-- <rule ref="vendor/spryker/architecture-sniffer/src/Project/Zed/ruleset.xml/OrmNewEntityNotInCommunicationRule"> <properties> <property name="ignoreClassPattern" value="#\\SomeModule\\#" /> </properties> </rule> --> </ruleset>
After that, run phpmd against your project-level ruleset instead of the vendor one, and change it freely for project needs:
vendor/bin/phpmd src/ (json|text|html) phpmd.xml --minimumpriority=4
The commands below use this project-level path.
Local Code Review Usage
For a local review, save the report to JSON and format it into a grouped, human-readable summary.
Save the report (scan all priorities for an AI-assisted review):
vendor/bin/phpmd src/ json vendor/spryker/architecture-sniffer/src/Project/ruleset.xml --minimumpriority 4 --reportfile architecture-results.json
or
vendor/bin/phpmd src/ json phpmd.xml --minimumpriority 4 --reportfile architecture-results.json
Format it:
vendor/bin/spryker-architecture format-project-results architecture-results.json [<output.txt>]
Without <output.txt> the formatted report is printed to stdout.
Baseline
Adopt the ruleset on an existing project without refactoring legacy code first: generate a baseline of the current violations and only fail on new ones.
# generate phpmd.baseline.xml in the project root
vendor/bin/phpmd src/ text phpmd.xml --generate-baseline
# subsequent runs ignore baselined violations
vendor/bin/phpmd src/ text phpmd.xml --baseline-file phpmd.baseline.xml
Use --update-baseline to drop violations that no longer exist. Store the baseline in version control and shrink it over time.
Debugging
Enable Xdebug for phpmd to step through rule code:
docker/sdk cli -x
PHPMD_ALLOW_XDEBUG=true vendor/bin/phpmd src/Pyz/ text phpmd.xml
Writing new sniffs
Add them to inside src folder and add tests in tests with the same folder structure.
Don't forget to update ruleset.xml.
Every sniff needs a description as full sentence:
protected const RULE = 'Every Foo needs Bar.'; /** * @return string */ public function getDescription(): string { return static::RULE; }
Every sniff needs to implement either the ClassAware, FunctionAware, InterfaceAware, or MethodAware interface to be recognised.
To validate that sniffer recognises your rule, check if your rule is listed in Zed UI > Maintenance > Architecture sniffer.
Also note:
- The rule names must be unique across the rulesets.
- Each rule should contain only one "check".
- Each rule always outputs also the reason (violation), not just the occurrence.
Setup
Run
./setup.sh
and
php composer.phar install
Testing
Don't forget to test your changes:
php phpunit.phar
Running code-sniffer on this project
Make sure this repository is Spryker coding standard conform:
php composer.phar cs-check
If you want to fix the fixable errors, use
php composer.phar cs-fix
Once everything is green you can make a PR with your changes.