valkyrja/phparkitect

PHPArkitect for the Valkyrja Project.

Maintainers

Package info

github.com/valkyrjaio/phparkitect

Homepage

Type:project

pkg:composer/valkyrja/phparkitect

Statistics

Installs: 125

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v26.2.1 2026-04-16 05:47 UTC

This package is auto-updated.

Last update: 2026-04-17 04:10:43 UTC


README

Valkyrja PHPArkitect

PHPArkitect architectural rules and custom expressions for the Valkyrja project.

PHP Version Require Latest Stable Version License Scrutinizer Coverage Status Psalm Shepherd Maintainability Rating

Build Status

Linting PHP Code Sniffer Build Status PHP CS Fixer Build Status
Coding Rules PHPArkitect Build Status Rector Build Status
Static Analysis PHPStan Build Status Psalm Build Status
Testing PHPUnit Build Status

Overview

This repository contains two things:

  1. Valkyrja\Arkitect\Rules — a reusable rule set that encodes the naming and namespace conventions used across the Valkyrja project. Drop it into any PHPArkitect config to enforce those conventions on your own code.

  2. Custom expressions — PHPArkitect Expression implementations that fill gaps in the built-in expression library.

Installation

composer require valkyrja/phparkitect

Usage

Reference Rules::getRules() from your phparkitect.php configuration file:

// phparkitect.php
use Valkyrja\Arkitect\Rules;

return Rules::getRules();

getRules() returns a closure that receives a PHPArkitect Config object and registers all rules against two class sets:

  • src/ — source rules (naming, namespaces, architectural constraints)
  • tests/ — test rules (finality, naming conventions for test helpers)

The paths are resolved relative to the directory three levels above src/Arkitect/Rules.php (i.e. the project root), matching the standard Valkyrja monorepo layout.

Run PHPArkitect as normal:

vendor/bin/phparkitect check

Rules Reference

Source Rules

No @author docblocks

All classes must not contain an @author docblock annotation.

Attributes

Rule Constraint
Classes with #[Attribute] must reside in *Attribute\ namespaces Attributes belong in dedicated namespaces
Classes in *Attribute\ namespaces must carry #[Attribute] Only attributes live in attribute namespaces
Classes outside *Attribute\* must not carry #[Attribute] Non-attributes must not be attributed

Constants

Rule Constraint
Final classes (excluding *Security and *Provider) must reside in *Constant\ Constants namespace
Classes in *Constant\ must be final Constants are sealed

Providers

Type Naming Namespace
ServiceProviderContract *ServiceProvider *Provider\
ComponentProviderContract *ComponentProvider *Provider\
CliRouteProviderContract *RouteProvider *Provider\
ListenerProviderContract *ListenerProvider *Provider\
HttpRouteProviderContract *RouteProvider *Provider\
All classes in *Provider\ *Provider suffix

Factories

Rule Constraint
Classes named *Factory must reside in *Factory\ Factories belong in factory namespaces
Classes in *Factory\ must be named *Factory Only factories live in factory namespaces

CLI Commands

Classes named *Command (outside Valkyrja\Cli\*, and not *Handler or *Middleware) must reside in *Cli\Command\ namespaces.

Security

Classes named *Security must reside in *Security\ namespaces and must be final.

Exceptions and Throwables

Rule Constraint
Classes named *Exception must reside in *Exception\ Exceptions namespace
Classes extending Throwable must reside in *Throwable\ Throwable objects belong in throwable namespaces
Classes implementing Throwable must be named *Exception Throwables are exceptions
Classes named *RuntimeException must reside in *Abstract\ and be abstract Base runtime exceptions are abstract
Classes named *InvalidArgumentException must reside in *Abstract\ and be abstract Base invalid argument exceptions are abstract

Types, Models, and Entities

Rule Constraint
Classes extending Type (outside Config, Entity, Model namespaces) must reside in *Type\ Types namespace
Classes extending Model (outside Config, Entity namespaces) must reside in *Model\ Models namespace
Classes extending Entity must reside in *Entity\ Entities namespace

Interfaces (Contracts)

Rule Constraint
Interfaces must reside in *Contract\ namespaces Contracts namespace
Classes in *Contract\ must be interfaces Only interfaces are contracts
Interfaces (except *Throwable) must be named *Contract Contract naming convention
Classes named *Contract must be interfaces Naming implies interface

Traits

Rule Constraint
Traits must reside in *Trait\ namespaces Traits namespace
Classes in *Trait\ must be traits Only traits live in trait namespaces
Traits must not be named *Trait* No "Trait" in the name
All classes must not be named *Trait* No "Trait" in any name

Abstract Classes

Rule Constraint
Abstract classes (outside *Factory and specific routing controller namespaces) must reside in *Abstract\ Abstract namespace
Classes in *Abstract\ must be abstract Only abstract classes live there
Abstract classes must not be named *Abstract* No "Abstract" in the name
Non-abstract classes must not be named *Abstract* No "Abstract" in any name

Enums

Rule Constraint
Enums must reside in *Enum\ namespaces Enums namespace
Classes in *Enum\ (outside Valkyrja\Type\Enum) must be enums Only enums live in enum namespaces
Enums must not be named *Enum* No "Enum" in enum names
Non-enums (outside Valkyrja\Type\Enum, excluding EnhancedEnumSupport) must not be named *Enum* No "Enum" in non-enum names

Test Rules

Rule Constraint
All classes must not contain @author docblocks Same as src
Test classes (in *Tests\, not *TestCase, *AttributeClass, *EnvClass, non-abstract, non-trait, outside Vendor) must be final Tests are sealed
Classes in *Classes\ (non-enum, non-trait) must be named *Class Test helper class naming
Classes in *Classes\ must not be named *Test Test helpers are not tests
Classes not named *Test must not reside in *Unit\ or *Functional\ Only tests live in test namespaces
Traits (not TestCase) in tests must reside in *Trait\ and be named *Trait Test trait conventions

Custom Expressions

NotHaveAttribute

Valkyrja\Arkitect\Expression\ForClasses\NotHaveAttribute

The inverse of PHPArkitect's built-in HaveAttribute. Evaluates to a violation when the target class does carry the specified PHP attribute.

use Valkyrja\Arkitect\Expression\ForClasses\NotHaveAttribute;

Rule::allClasses()
    ->that(new NotResideInTheseNamespaces('*Attribute\\*'))
    ->should(new NotHaveAttribute(Attribute::class))
    ->because('Non-attribute classes must not carry #[Attribute]');

Constructor:

new NotHaveAttribute(string $attribute)
Parameter Description
$attribute Fully qualified class name of the PHP attribute to check

Violation message format:

<FQCN> should not have the attribute <attribute> because <reason>

Workflows

The _workflow-call.yml reusable workflow runs PHPArkitect against the calling repository's source. It is designed to be called from other repositories via workflow_call.

Inputs

Input Type Default Description
paths string Required. YAML filter spec with two keys: ci (CI config files that trigger a base-branch fetch) and files (all files that trigger the check).
post-pr-comment boolean true Post a PR comment on failure and remove it on success. Disable when the calling workflow handles its own reporting.
composer-options string '' Extra flags passed to every composer install step (e.g. --ignore-platform-req=ext-openswoole).
php-version string '8.4' PHP version to use.
ci-directory string '.github/ci/phparkitect' Path to the CI directory containing composer.json and the tool config.
extensions string 'mbstring, intl' PHP extensions to install via shivammathur/setup-php.

Usage

jobs:
  phparkitect:
    uses: valkyrjaio/phparkitect/.github/workflows/_workflow-call.yml@26.x
    permissions:
      pull-requests: write
      contents: read
    with:
      php-version: '8.4'
      paths: |
        ci:
          - '.github/ci/phparkitect/**'
          - '.github/workflows/phparkitect.yml'
        files:
          - '.github/ci/phparkitect/**'
          - '.github/workflows/phparkitect.yml'
          - 'src/**/*.php'
          - 'composer.json'
    secrets: inherit

secrets: inherit is required to pass the VALKYRJA_GHA_APP_ID and VALKYRJA_GHA_PRIVATE_KEY org secrets used for PR comments.