Download the PHP package scafera/integration without Composer
On this page you can find all versions of the php package scafera/integration. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download scafera/integration
More information about scafera/integration
Files in scafera/integration
Package integration
Short Description External system integration for the Scafera framework
License MIT
Homepage https://github.com/scafera/integration
Informations about the package integration
scafera/integration
External system communication for the Scafera framework. Provides an enforceable gateway pattern for calling third-party APIs — all behind Scafera-owned types.
Internally adopts symfony/http-client. Userland code never imports Symfony HttpClient types — boundary enforcement blocks it at build time. All alternative HTTP mechanisms (cURL, file_get_contents with HTTP URLs) are also blocked.
Provides: External system communication for Scafera — a gateway pattern where each class wraps one third-party system with business-level methods.
HttpClient(5 methods: get/post/put/patch/delete) andResponse(statusCode/json/body/headers/header) are Scafera-owned types; gateways wire up via#[Integration]. All HTTP escape hatches (Symfony HttpClient, cURL,file_get_contents/fopenwith HTTP URLs) are blocked outsideIntegration/.Depends on: A Scafera host project with an
Integration/layer (e.g.src/Integration/underApp\Integration). Per-integration config underintegration:inconfig/config.yaml; secrets belong inconfig.local.yaml(git-ignored).Extension points:
- Attribute —
#[Integration('name')]resolves to the configuredHttpClient;#[Integration('name', 'key')]resolves to a per-integration config value (ADR-065)- User gateways — one class per external system in
Integration/..., class name must end withGateway(enforced byGatewayNamingValidator), business-level methods only- Config —
integration:section inconfig/config.yamldeclares each integration'sbase_url,auth, and any custom keys (injectable via the two-arg attribute)- Testing —
HttpClientconstructor accepts an optionalHttpClientInterface(e.g.MockHttpClient) for test doubles; the bundle never passes it in productionNot responsible for: Raw HTTP outside
Integration/(Symfony HttpClient, cURL,file_get_contents/fopenwith HTTP URLs — blocked byHttpClientLeakageValidator,HttpClientBoundaryValidator) · auto-throwing on HTTP errors (Responsenever throws; the gateway decides) · full URLs in gateway methods (relative paths only; base URL from config) · secret storage (belongs inconfig.local.yaml, notconfig.yaml) · unusedintegration:config keys (flagged byUnusedIntegrationConfigValidator).
This is a capability package. It adds optional external system integration to a Scafera project. It does not define folder structure or architectural rules — those belong to architecture packages.
What it provides
HttpClient— wraps Symfony HttpClient with 5 methods (get, post, put, patch, delete)Response— wraps Symfony response with 5 methods (statusCode, json, body, headers, header)#[Integration('name')]— attribute for wiring gateways to configured HttpClient instances#[Integration('name', 'key')]— attribute for injecting integration-specific config values into gateways (ADR-065)HttpClientLeakageValidator— blocks all HTTP escape hatches insrc/GatewayNamingValidator— enforces*Gatewaynaming inIntegration/HttpClientBoundaryValidator— ensuresHttpClientis only used inIntegration/layerIntegrationConfigBoundaryValidator— ensures#[Integration('name', 'key')]config values are only used inIntegration/layerUnusedIntegrationConfigValidator— flags config values defined inintegration:but not referenced in any gateway
Design decisions
- Gateway, not HTTP client wrapper — a wrapped HTTP client would scatter
$http->post()calls across the codebase. Gateways enforce one class per external system with business-level methods (ADR-064). #[Integration]attribute for wiring — extends Symfony's#[Autowire], same pattern as#[Config]in the kernel. Explicit at the injection site, greppable, validatable, refactor-safe (ADR-064). With a second argument, resolves integration-specific config values (ADR-065).- Relative paths only — gateways use endpoint paths (
'/charges'), not full URLs. Base URL is configured once inconfig.yaml. - All HTTP escape hatches blocked — Symfony HttpClient, cURL,
file_get_contentswith HTTP URLs,fopenwith HTTP URLs. If you need HTTP, you go through a gateway.
Installation
The bundle is auto-discovered via Scafera's symfony-bundle type detection. No manual registration needed.
Requirements
- PHP >= 8.4
- scafera/kernel
Configuration
If an integration has different base URLs per environment (e.g., sandbox vs production), override base_url in config.local.yaml as well.
Gateway
A gateway is one class per external system with business-level methods:
Gateway rules
- Class name must end with
Gateway— enforced by validator - One class per external system
- Business-level methods only —
createPayment(), notpost() - No HTTP types in public method signatures — return arrays or domain objects
- No full URLs — endpoint paths only, base URL from config
Using a gateway in a service
Services inject gateways via constructor — same as any Scafera dependency:
Integration-specific configuration
Integrations can carry arbitrary config values beyond base_url and auth. These are registered as container parameters and injected via the same #[Integration] attribute with a second argument:
The gateway receives config values alongside the HttpClient:
#[Integration('name')] without a second argument resolves to the HttpClient service. #[Integration('name', 'key')] resolves to the config value. The HttpClient itself has no awareness of these values — they are resolved by the container before the gateway is constructed.
HttpClient API
The $data array is sent as JSON body. For other content types (form-encoded, multipart), use the $options array directly (e.g., $this->http->post('/upload', [], ['body' => $formData])).
Response API
HTTP errors do not throw automatically — error handling is the gateway's responsibility.
Testing
Testing services that use gateways
Mock the gateway, not the HTTP client:
Testing gateways themselves
The HttpClient constructor accepts an optional HttpClientInterface for testing — the bundle never passes it (engine stays hidden in production):
Boundary enforcement
| Blocked | Use instead |
|---|---|
Symfony\Contracts\HttpClient\* |
Scafera\Integration\HttpClient in a Gateway class |
Symfony\Component\HttpClient\* |
Scafera\Integration\HttpClient in a Gateway class |
curl_* functions |
Scafera\Integration\HttpClient in a Gateway class |
file_get_contents with HTTP URLs |
Scafera\Integration\HttpClient in a Gateway class |
fopen with HTTP URLs |
Scafera\Integration\HttpClient in a Gateway class |
Scafera\Integration\HttpClient outside Integration/ |
Inject the gateway, not the HTTP client |
#[Integration('name', 'key')] outside Integration/ |
Integration config values belong in gateways only |
Unused config keys under integration: |
Remove unused keys or reference them in a gateway |
Enforced via validators (scafera validate). The HttpClient and integration config values are only allowed inside the Integration/ layer — services and controllers inject gateways, not HTTP clients or integration config.
License
MIT