mirafive/sdk-symfony
Mirafive SDK for Symfony offers a framework-friendly integration layer for the Mirafive PHP SDK, with bundle configuration and service wiring to help Symfony developers connect to Mirafive APIs quickly and reduce manual setup.
Architecture fit — This release is a Symfony bundle (mirafive/sdk-symfony, AbstractBundle), not a Laravel package. It cannot be installed into a Laravel application as-is: AbstractBundle, kernel.terminate/kernel.reset, Twig functions, and Symfony Messenger are all outside Laravel's runtime. Its real value to a Laravel roadmap is as a reference implementation of the core SDK's framework seams (enabled, flushOnShutdown, flagsRefreshSeconds, handOff, deliverPrepared()) on mirafive/sdk-php 1.0. Every integration decision the Symfony bundle makes has a direct Laravel analogue, so it de-risks our own adapter — but it does not remove the need to build one.
Integration feasibility — Straightforward if we accept building a thin Laravel package on the same core. Mapping is close to 1:1:
| Symfony bundle | Laravel equivalent |
|---|---|
MiraFiveBundle + mirafive config tree |
Service provider + config/mirafive.php (MIRAFIVE_* env keys reused verbatim) |
Autowired MiraFive\Mira, MiraFlags |
Container singletons / facades |
kernel.terminate, console.terminate |
terminating() callback, Artisan::terminating() |
kernel.reset (worker runtimes) |
Octane RequestTerminated/RequestReceived, queue worker JobProcessed/Looping |
DeliverBatch via Messenger |
Queued job dispatched with deliverPrepared() payload |
mirafive_script(), mirafive_flags() Twig funcs |
Blade directives / @mirafiveScript, @mirafiveFlags |
bin/console mirafive:check |
php artisan mirafive:check |
MiraFake + InteractsWithMira |
Test double + trait, Mira::fake() |
The single-process MiraFlags guarantee, the Cache-Control: private, no-store header on the flags bootstrap, and the "no secret key or enabled: false ⇒ record nothing" no-op contract are all behaviours we should copy exactly rather than reinvent.
Technical risk — Medium, concentrated in lifecycle and delivery semantics rather than in the API surface:
kernel.reset is the Symfony signal; Laravel has no single equivalent. Flush-on-JobProcessed plus reset-on-Looping must be validated under Horizon and Octane, not just under php artisan serve.mirafive/sdk-php 1.0 seams. Both packages are at 1.0.0 with no compatibility history; a 1.1 core that shifts handOff() or deliverPrepared() breaks us.send() stays synchronous while batches go through Messenger "delivered by the worker's own client byte for byte" — that phrasing implies a deliberate guarantee we cannot verify from release notes. If async delivery is not truly byte-identical, dedupe/ordering assumptions in our analytics layer are at risk.Key questions — (1) Is a first-party mirafive/sdk-laravel planned, and on what timeline? Building our own is only justified if the answer is "no" or "later." (2) Does the core guarantee async deliverPrepared() payloads are identical to the synchronous send() payload, and is that contractual or incidental? (3) What is the supported mirafive/sdk-php constraint, and is there a deprecation policy for the seam methods? (4) Under Octane, is MiraFlags reset per request or per worker, and what is the cache-miss cost of flags.refresh_seconds? (5) Does mirafive:check require outbound network at deploy time — i.e. can it run in a restricted CI/deploy step? (6) What happens on flush failure at terminate — silent drop, retry, or logged?
Stack fit — Poor as a direct dependency (Symfony-only), strong as a specification. Treat v1.0.0 as the canonical behaviour contract for our Laravel adapter and mirror its config schema exactly so that documentation, env vars (MIRAFIVE_SECRET_KEY, MIRAFIVE_WEBSITE_KEY, MIRAFIVE_HOST, MIRAFIVE_MODE, MIRAFIVE_SCRIPT_MODE, MIRAFIVE_ENABLED, MIRAFIVE_MESSENGER, MIRAFIVE_FLAGS_REFRESH_SECONDS, MIRAFIVE_FLAGS_CACHE, MIRAFIVE_TEST), and ops runbooks are portable across both frameworks.
Migration path — No migration required: nothing is currently deployed. Sequence: (a) adopt mirafive/sdk-php ^1.0 directly in the Laravel app behind our own thin wrapper interface, so the wrapper — not the vendor SDK — is what application code calls; (b) build the provider + config + lifecycle wiring; (c) add Blade directives; (d) add mirafive:check; (e) add the test double. This keeps the option of swapping to a first-party Laravel package later without touching call sites.
Compatibility — Assume PHP 8.1+ and Laravel 10/11 as the target; the release notes state no constraints, so confirm composer.json requirements before committing. Symfony Messenger has no Laravel counterpart, so the messenger config block should be dropped in favour of Laravel's queue connection — do not attempt to emulate it. Validate against Octane and Horizon explicitly; those are the two runtime modes where the Symfony bundle's lifecycle work actually earns its keep.
Sequencing — Phase 1: core SDK + wrapper + config + no-op behaviour (enabled: false) verified in staging — this alone answers "does it record nothing when it should." Phase 2: request/terminate flush + Octane and queue-worker reset. Phase 3: Blade script/flags tags and the no-store header. Phase 4: async batch delivery via queued job. Phase 5: artisan mirafive:check wired into post-deploy verification. Phase 6: test double and CI coverage. Ship Phase 1–2 behind a flag before touching async delivery — the async path is where the dedupe risk lives.
Maintenance — We own a fork-in-spirit adapter, not a dependency. Budget ongoing maintenance for core SDK upgrades (two 1.0.0 packages with no upgrade history is a real churn risk) plus Octane/Horizon lifecycle changes in Laravel majors. The Symfony bundle's own maintenance is not our cost, but it is our early-warning signal: watch its releases for seam changes before bumping the core.
Support — Support burden lands on our platform team, not the vendor, for anything Laravel-specific. Escalation to MiraFive is viable for core SDK issues (payload shape, flags semantics, deliverPrepared() behaviour) and for behaviour-parity questions against the Symfony bundle. Document the wrapper interface as the supported surface; discourage direct MiraFive\Mira usage in application code.
Scaling — Buffered-batch + terminate-flush is the right pattern for high-request-volume PHP and avoids per-request network calls, which is the single biggest win here. Two scaling caveats: batch size is bounded by PHP memory and worker lifetime, so under Octane a long-lived worker accumulates across many requests and must be reset — the kernel.reset analogue is not optional. And flags are one-per-process with a refresh_seconds TTL, so flag propagation latency equals TTL × worker count; set expectations for how fast a kill-switch actually takes effect.
Failure modes — Ranked: (1) double-flush from core shutdown flush left enabled alongside our own — duplicated analytics events, silent, hard to detect; (2) flush on terminate lost when a request is killed or a worker is OOM-reaped — data loss with no error surfaced unless we add logging; (3) async batch delivery failing in the queue with no dead-letter handling, dropping batches quietly; (4) stale flags in long-lived workers making a kill-switch appear ineffective; (5) missing secret key silently no-op'ing in production after a bad env deploy — the "records nothing" contract is good design but needs an alert, not just silence. Require explicit logging/metrics on flush success, flush failure, and no-op activation.
Ramp-up — Low for anyone who knows Laravel's service-provider and Octane lifecycle; the concepts (buffered flush, process-scoped singleton, test fake) are standard. The non-obvious learning is entirely in the seams: which component owns the flush, when flags reset, and why send() is synchronous while batches are not. Two concrete ramp artifacts: a one-page lifecycle diagram mapping Symfony events to Laravel hooks, and a mirafive:check receipt from staging as the acceptance gate. Estimate one engineer-week for a working Laravel adapter through Phase 4, plus a second week for Octane/Horizon hardening and test coverage.
How can I help you explore Laravel packages today?