johnnickell / fight-common
A shared PHP library for Hexagonal Architecture, CQRS, and reusable domain primitives
Requires
- php: >=8.5
- psr/cache: ^3.0
- psr/container: ^2.0
- psr/http-client: ^1.0
- psr/http-factory: ^1.1
- psr/http-message: ^2.0
- psr/log: ^3.0
Requires (Dev)
- doctrine/dbal: ^4.4
- doctrine/orm: ^3.6
- dragonmantank/cron-expression: ^3.0
- guzzlehttp/guzzle: ^7.10
- guzzlehttp/promises: ^2.3
- guzzlehttp/psr7: ^2.9
- lcobucci/jwt: ^5.6
- league/flysystem: ^3.0
- mockery/mockery: ^1.6
- phpseclib/phpseclib: ^3.0
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^13.0
- rector/rector: ^2.4
- squizlabs/php_codesniffer: ^4.0
- symfony/dependency-injection: ^8.0
- symfony/event-dispatcher: ^8.0
- symfony/filesystem: ^8.0
- symfony/finder: ^8.0
- symfony/http-foundation: ^8.0
- symfony/http-kernel: ^8.0
- symfony/mailer: ^8.0
- symfony/mercure: ^0.7
- symfony/messenger: ^8.0
- symfony/process: ^7.0
- symfony/routing: ^8.0
- twig/twig: ^3.0
- twilio/sdk: ^8.0
Suggests
- doctrine/dbal: Required by the custom doctrine data types
- doctrine/orm: Required by the doctrine unit of work, audit repository, and base repository
- dragonmantank/cron-expression: Required by the Scheduler for cron expression parsing
- guzzlehttp/guzzle: Required by the guzzle http client adapter
- guzzlehttp/promises: Required by the guzzle http client adapter
- guzzlehttp/psr7: Required by the guzzle http client adapter
- lcobucci/jwt: Required by the jwt token encoder and decoder
- league/flysystem: Required by the flysystem file storage adapter
- phpseclib/phpseclib: Required by the SFTP file transport adapter
- symfony/dependency-injection: Required by the Symfony compilation passes
- symfony/event-dispatcher: Required by the validation and other event subscribers
- symfony/filesystem: Required for the filesystem adapter
- symfony/http-foundation: Required for the JSend response and other HTTP related utilities
- symfony/http-kernel: Required for the kernel middleware and other HTTP related utilities
- symfony/mailer: Required by the Symfony mail transport and attachment adapters
- symfony/mercure: Required by the Mercure hub publisher
- symfony/messenger: Required by the async messenger command bus and event dispatcher
- symfony/process: Required by the Symfony process runner adapter
- symfony/routing: Required for the URL generator
- twig/twig: Required by the Twig template engine adapter
- twilio/sdk: Required by the Twilio SMS transport adapter
This package is auto-updated.
Last update: 2026-08-12 07:11:04 UTC
README
A shared PHP library for projects implementing Hexagonal (Ports & Adapters) / Clean Architecture. Provides foundational building blocks including value objects, typed collections, CQRS messaging, a composable validation system, and infrastructure adapters.
Documentation · Quick Start · Changelog
Requirements
- PHP 8.5+
- Docker (for local tooling)
Installation
composer require johnnickell/fight-common
Optional adapters require additional packages — install only what you need:
composer require doctrine/orm # Doctrine data types and unit of work composer require doctrine/dbal # Database health check and nonce replay prevention composer require symfony/http-kernel # HTTP middleware and JSend response composer require lcobucci/jwt # JWT encoder and decoder composer require guzzlehttp/guzzle # HTTP client adapter
Architecture
Dependencies flow inward only. The Domain has no external dependencies. The Application layer depends on Domain interfaces only. Adapters depend on both.
Domain ← pure business logic, no framework dependencies
Application ← orchestrates domain via interfaces
Adapter ← concrete infrastructure implementations
What's Inside
Domain
Value Objects — immutable, self-validating objects that model domain concepts:
StringObject,MbStringObject,JsonObject— string and JSON primitivesEmailAddress,Uri,Url— internet value types with RFC-compliant validationUuid,UniqueId,MessageId— identifier types with multiple creation strategies
Specifications — composable business rules:
$rule = $isActive->and($hasVerifiedEmail)->and($isNotBanned->not()); $rule->isSatisfiedBy($user); // true or false
Collections — fully typed collection hierarchy:
ArrayList— ordered list with sort, slice, pagination, and predicate searchHashSet— set operations: union, intersection, difference, complementHashTable— key-value map with typed keys and valuesSortedSet/SortedTable— ordered structures backed by a Red-Black tree with floor, ceiling, rank, and range operationsArrayStack,LinkedStack,ArrayQueue,LinkedQueue,LinkedDeque— typed stack and queue structures
Messaging — CQRS message contracts:
CommandMessage,QueryMessage,EventMessagewithMetasupport- Serializable to/from array and JSON
Repository — pagination and result set contracts:
Pagination— page, perPage, orderingsResultSet— paginated records with total count and page metadata
Application
Validation — rule-based field validation:
$service->validate([ ['field' => 'email', 'label' => 'Email', 'rules' => 'required|email'], ['field' => 'username', 'label' => 'Username', 'rules' => 'required|min_length[3]|max_length[20]'], ], $input);
CQRS Buses — CommandBus and QueryBus with pipeline middleware support.
Observability — application-layer ports for health checks, metrics, and audit logging:
HealthAggregator/HealthCheck— compose N checks into aHealthReport(overall status, per-check results)MetricsCollector—increment,gauge,histogramwith tag support; bus middleware auto-instruments handlersAuditLog/AuditRepository— structured business-fact records (actor, action, timestamp, context); queryable by actor, action, or time range
Serializers — JsonSerializer and PhpSerializer for message serialization.
Container — PSR-11 compatible service container with singleton and factory registration.
Adapters
| Adapter | Requires |
|---|---|
Doctrine data types (Uuid, Uri, Url, StringObject, JsonObject, etc.) |
doctrine/dbal |
DoctrineUnitOfWork |
doctrine/orm |
SimpleEventDispatcher, ServiceAwareEventDispatcher |
— |
RoutingCommandBus, RoutingQueryBus |
— |
MetricsCommandFilter, MetricsQueryFilter |
— |
HealthReporter, DatabaseHealthCheck |
doctrine/dbal |
HttpEndpointHealthCheck |
any HttpClient adapter |
NullMetricsCollector, NullAuditLog |
— |
StatsDMetricsCollector |
ext-sockets |
LoggingAuditLog |
any PSR-3 logger |
HmacAuthenticator, HmacRequestService, HmacWebhookDispatcher |
— |
InMemoryNonceRepository |
— |
DoctrineNonceRepository |
doctrine/dbal |
PhpPasswordHasher, PhpPasswordValidator |
— |
JwtEncoder, JwtDecoder |
lcobucci/jwt |
JsonRequestMiddleware, JSendResponse |
symfony/http-foundation |
SymfonyFilesystem |
symfony/filesystem |
EventSubscriberCompilerPass |
symfony/dependency-injection |
Development
All tooling runs inside a PHP 8.5 Docker container via scripts in ./bin/. Never use vendor/bin/ directly.
./bin/phpunit # complete suite with disposable MySQL/PostgreSQL and coverage ./bin/phpunit --fast # fast suite; excludes server-database tests and is not submit evidence ./bin/phpunit --filter foo # filter the complete suite by test name ./bin/rector process src/ # run code modernization ./bin/deptrac # enforce inward architecture and complete classification ./bin/composer require pkg # manage dependencies
The complete PHPUnit command creates disposable MySQL 8.4.11 and PostgreSQL 17
containers, injects their DSNs, and removes the containers and isolated network
on success, failure, or interruption. Missing or unreachable complete-suite
database infrastructure is a failure, never a skipped test. Use --fast only
for deliberately focused local feedback; it is not submit or release evidence.
Coverage
100% code coverage is required and enforced by PHPUnit configuration. All test classes must declare #[CoversClass].
License
MIT