symfony-bundles/bundle-dependency
A Symfony bundle for managing dependencies between bundles. Declare required bundles and let the package verify installation and loading order, helping modular Symfony applications avoid missing or misordered dependencies.
Framework mismatch is the headline finding. The brief frames this as a "Laravel/PHP package," but bundle-dependency is Symfony-only by construction: it hooks Symfony's bundle registration lifecycle (bundles.php, AppKernel::registerBundles()), depends on Symfony bundle class metadata, and resolves a dependency graph over Bundle subclasses. Laravel has no equivalent concept — it has service providers, config/app.php provider lists, package discovery via extra.laravel.providers, and deferred providers. There is zero code reuse available for a Laravel stack, and the analog in Laravel (provider registration order) is generally better addressed by register() vs boot() discipline and deferred providers than by a third-party graph resolver. If our estate is Laravel, the recommendation is to decline and close.
Architecture fit (assuming a Symfony stack). Moderate at best. The package solves a real but narrow problem: explicit, hand-maintained bundle ordering in bundles.php. Modern Symfony (4+) reduced this problem substantially — bundles.php is an explicit array that Flex manages, and typical apps carry 10–20 bundles, not the 50+ that motivated this in the Symfony 2/3 era. The deeper architectural flaw: dependencies can only be declared on bundle classes we control. Third-party bundles — precisely the ones with implicit ordering constraints and undocumented requirements — cannot be annotated without subclassing or forking. So the resolver's graph is structurally incomplete exactly where the risk lives, producing false confidence.
Integration feasibility. Low-to-moderate. Adoption requires owning the bundle registration path: a custom Kernel::registerBundles() or an AppKernel subclass that consults the resolver before returning the bundle list. That is a high-blast-radius edit to the application's boot path, and a failure here means the app does not start at all. It is not a drop-in library; it is an invasive kernel modification for a convenience feature.
Technical risk: high. Last release February 2018, 19 stars, repository listed as unknown/unlinked, composite score 0.195. That profile is "abandoned hobby utility," not "foundation dependency." Concrete risks: PHP 7.x-era code with no guarantee of PHP 8.x compatibility (return types, deprecations, dynamic properties); Symfony 5/6/7 changes to bundle metadata and kernel contracts; no security disclosure process or CVE tracking; single-maintainer abandonment with no successor. A boot-path dependency on unmaintained code is the worst place to carry abandonment risk.
Key questions to resolve before any decision:
Stack fit. Laravel: reject outright — no applicable mechanism, and the analogy (provider ordering) is better solved natively. Symfony 3.x: plausible but that version is itself out of support. Symfony 4.x/5.x: viable only as an internal, vendored utility with the kernel wrapper isolated. Symfony 6/7: assume incompatible until proven otherwise; do not plan around it.
Recommended shape if we proceed at all: extract, don't adopt. Take the topological-sort and cycle-detection logic (small, MIT, easy to reimplement), place it in an internal Kernel helper, and expose dependencies via a simple static method or attribute on our first-party bundles. This retains ~90% of the benefit — deterministic order, early circular-dependency errors, no manual bundles.php shuffling — while removing the abandoned-dependency and PHP-version risk entirely. Treat third-party bundles as fixed pins with explicit ordering assertions in configuration rather than as graph nodes.
Migration path. (1) Inventory current bundles.php/AppKernel order and record which pairs are genuinely order-sensitive. (2) Implement the resolver in report-only mode: compute the topological order, diff it against the current committed order, log discrepancies, change nothing. (3) Run report-only through at least one full release cycle and one cache:clear/cold-boot in staging. (4) Only then switch the kernel to consume the computed order. (5) Rollback is trivial and must be documented: revert the kernel wrapper, restore the static bundles.php, deploy.
Compatibility. Verify against our exact PHP and Symfony versions in the supported matrix, including the oldest we support. Check Composer constraints and whether the package's Symfony version bounds are satisfiable without aliasing. Test cold boot, warm cache, cache:clear, and prod build in CI — not just bin/console locally.
Sequencing. Spike first (1–2 days): can it boot on our Symfony version at all? If yes, decide fork-vs-reimplement. If reimplement, this is a small internal ticket, not a dependency decision. Either way, gate the outcome behind a CI check that fails when committed order drifts from computed order — that check is the durable value, not the library.
Maintenance. Upstream maintenance is effectively zero, so ownership transfers to us on day one. Budget ongoing cost of roughly 2–4 engineer-days per year for PHP/Symfony upgrade compatibility if vendored, plus an annual security review. Every PHP minor upgrade becomes a re-validation event for a component that touches application boot.
Support. No vendor, no SLA, no release cadence, no issue triage. Internal support means whoever last touched it; that is a bus-factor-of-one risk on critical-path code.
Scaling. Runtime cost is negligible — graph resolution happens once at boot and results should be cached. Value scales with bundle count: roughly, below ~15 bundles this is overhead with no payoff; above ~30 with genuine ordering constraints, or with multiple teams adding bundles concurrently, the CI drift check earns its keep. The bottleneck it addresses is human coordination, not machine throughput.
Failure modes. Worst case is total application unavailability at boot — a bad graph or an unresolved node means the kernel throws and nothing serves. Circular-dependency detection is the package's genuine strength and fires early, which is the right time. Real risks are more insidious: false negatives (third-party bundles outside the graph, so constraints go unexpressed); false confidence (teams believe they have solved ordering, when container compilation and compiler-pass priority still govern service order — this package does nothing for that); deployment-time failures surfacing on cache:clear in prod rather than in CI; and silent divergence if someone edits bundles.php by hand and bypasses the resolver. Mitigate with the CI drift check, a fail-fast boot test in the pipeline, and a single documented rule that bundles.php is generated, not hand-edited.
Ramp-up. The concept is easy to teach — declare what you need, the resolver sorts it — and the code surface is small; a mid-level engineer is productive in under a day. The harder ramp-up is conceptual: engineers must understand that bundle order ≠ service order, and that dependencies can only be declared on bundles we own. Document both limits prominently, or the team will over-trust the tool and misdiagnose container-ordering bugs as resolver failures.
Bottom line for the product decision: if the target stack is Laravel, decline — no fit. If Symfony, do not adopt the package as a dependency; reimplement the ~100-line sort internally under our own maintenance, ship it report-only first behind a CI drift check, and treat the abandoned upstream as design input rather than operational code.
How can I help you explore Laravel packages today?