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.
Check compatibility before anything else. The last tagged release is February 2018, which puts it in the Symfony 3.4 / 4.0 era, PHP 7.x, and Doctrine annotations. Run composer require symfony-bundles/bundle-dependency --dry-run and read the constraints. On PHP 8 / Symfony 5+ expect to need doctrine/annotations and to test on a throwaway branch first; annotations were deprecated in favor of PHP attributes, and this package almost certainly predates that.
Install and register:
composer require symfony-bundles/bundle-dependency
Then add the bundle to config/bundles.php (or AppKernel::registerBundles() for legacy apps). Register it early — it needs to participate before or during bundle resolution.
Read three things in vendor/symfony-bundles/bundle-dependency/src/ before writing code, because the README is thin and the exact API names matter:
Annotation/ or similar) — this is the syntax you put on bundle classes. The examples below use @RequiresBundle, but substitute the real name.sort, topolog, resolve) — the entry point that turns annotated bundles into an ordered list.DependencyInjection/) — this tells you whether the package reorders bundles or only validates their order. That distinction drives your whole integration strategy.First use case. In a scratch branch, pick two bundles where B genuinely needs A initialised first. Annotate B:
/**
* @RequiresBundle(Acme\ABundle::class)
*/
class BBundle extends Bundle
{
}
Then either feed your bundle list through the package's resolver, or boot the kernel and see what the package reports. Confirming the mechanism on two bundles is the fastest way to learn the package — do that before annotating a dozen bundles.
Verify the result. bin/console debug:container --parameter=kernel.bundles (or a temporary var_dump in registerBundles()) shows the actual boot order. Compare it with what you declared.
One direction only: "what I need", never "what needs me". Annotations describing requirements keep the graph a DAG and make each annotation independently safe to delete. Do not model reverse edges.
Centralise the list and resolve once. In Symfony Flex, config/bundles.php is a plain require, so it can execute code. If the package exposes a resolver, this is the cleanest integration:
// config/bundles.php
use SymfonyBundles\BundleDependency\DependencyResolver; // verify name in src/
return DependencyResolver::sort([
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Acme\ABundle::class => ['all' => true],
Acme\BBundle::class => ['all' => true],
]);
If the package only validates ordering rather than reordering, keep the array hand-ordered and treat the package as a lint step. Either way, there should be exactly one source of truth — not annotations and hand-ordering comments.
Wrap vendor bundles you cannot annotate. If VendorBundle must precede yours and you can't edit it, create a tiny local bundle whose only job is @RequiresBundle(VendorBundle::class), and require that local bundle from the dependent one. Alternatively, resolve only your own bundles and keep third-party ones in a small, explicit ordered block.
Make CI the primary consumer. The real value is failing fast on missing or circular dependencies. Add a CI step that boots the kernel (or invokes the resolver directly) for each environment — dev, test, prod — because an env-specific bundle list can hide a missing dependency that only appears in prod.
Do not rely on bundle order for container configuration. Bundle registration order affects build() / boot() order, but compiler passes and prependExtension merging still need explicit priorities. If two bundles contribute config that must merge in a particular sequence, use a CompilerPass with a priority — not this resolver.
Incremental migration. Annotate the "leaf" dependency of each cluster first, run the resolver, fix errors, repeat. Remove manual ordering comments as you go, otherwise humans will silently reorder the array and defeat the purpose.
Keep the graph environment-stable. Don't declare DebugBundle / WebProfilerBundle as hard dependencies of application bundles. Either keep the graph identical across environments, or resolve per environment with deliberate, documented divergence.
Unit-test the graph. If the resolver is a standalone class, test it with stub bundle classes: missing dependency, cycle A → B → A, self-cycle. Those three tests are your regression net for future annotation edits.
doctrine/annotations installed and the reader service enabled. Bundle classes must be named, autoloadable, and non-anonymous — the reader looks them up by FQCN.bundles.php.bin/console cache:clear after editing annotations, and remember that cache:warmup in prod can surface errors that dev never showed.composer.json. A bundle installed but disabled in bundles.php, or enabled only in dev, will be reported as missing. Check the bundle list for the active environment.kernel.bundles is populated before build(), so passes can inspect the final order — but service definitions from two bundles still merge according to compiler-pass priority, not bundle order.var_dump before sorting) and log the final list. When boot fails deep in a third bundle, knowing the resolved order saves hours.composer.json require is the contract for library dependencies. This package is application-level ordering sugar for bundles you control.How can I help you explore Laravel packages today?