Portable integration · Framework-free
Framework-free
Construct portable services directly and add infrastructure adapters only at the application boundary.
The portable baseline¶
Framework-free integration is the reference composition, not a reduced support tier. Values, collections, specifications, messages, repositories, and neutral Application services require no framework adapter. Install only Fight Common to begin:
Use each component guide for its portable construction and behavior. Add an Adapter only when the application crosses a real infrastructure boundary such as a database, HTTP transport, filesystem, mailer, or process.
Compose one capability¶
Application services depend on Domain and Application contracts. The outer bootstrap constructs the chosen adapter and supplies it to the use case. Keep provider configuration beside that construction so replacing a transport does not change the use case.
For example, select GuzzleClient for outbound HTTP, a Flysystem adapter for file storage,
SymfonyMailTransport for mail, or SymfonyProcessRunner for processes only when the application uses that
capability. Each optional package is independently selectable; installing Fight Common does not install them.
Use the Fight container when useful¶
Fight\Common\Application\Service\Container is a small PSR-11 container for explicit composition. Register
shared services with set() and transient factories with factory(). It does not scan application code or
autowire dependencies.
Fight\Common\Adapter\ServiceContainer\Fight\ContainerCapabilityRegistrar provides bounded helpers for
synchronous messaging, template helpers, and a configured Fight HTTP transport with its PSR-18 view. Invoke only
the registrar for the selected capability. Direct constructor wiring remains valid.
Provider and operations boundaries¶
Shared adapters cover Doctrine/DBAL persistence, Guzzle and PSR-18 HTTP, Flysystem storage, Twig templating, Symfony Mailer/Filesystem/Process/Messenger, Twilio SMS, Mercure publication, and PSR-3 observability. The application chooses concrete packages, configuration, credentials, migrations, transaction boundaries, retry policy, worker supervision, and shutdown behavior.
Async delivery through Messenger remains at least once. The application owns brokers, topology, retries, failure storage, workers, idempotency, and any durable outbox. Portable scheduling likewise needs an application-owned invocation loop and lock backend.
Failure boundaries¶
Do not translate provider failures into success at the composition root. Preserve the component guide's failure contract, attach operational context at the Adapter edge, and let the Application use case decide whether a failure is retryable. A null or logging adapter is a deliberate operating mode, not proof that an external side effect occurred.
Continue with Dependency Injection, Messaging, or the complete framework support matrix.