Dependency Resolution
Managing module dependencies and load order
Declaring Dependencies
In your module.json:
{
"name": "Blog",
"requires": {
"Core": "^1.0",
"Media": ">=2.0",
"Categories": "~1.5"
}
}
Version Constraints
| Constraint | Meaning |
|---|---|
^1.0 |
Compatible with 1.x (>=1.0.0 <2.0.0) |
~1.5 |
Allows patch updates (>=1.5.0 <1.6.0) |
>=2.0 |
2.0 or higher |
>1.0 <3.0 |
Between versions |
1.2.3 |
Exact version |
* |
Any version |
Load Order
Modules load in dependency order:
Core (no dependencies) → loads first
↓
Media (requires Core) → loads second
↓
Categories (requires Core) → loads third
↓
Blog (requires Core, Media, Categories) → loads last
The resolver uses topological sorting to determine the correct order.
Checking Dependencies
View Module Dependencies
php artisan modular:status Blog
View What Depends on a Module
php artisan modular:dependents Core
Output:
Modules depending on Core:
├── Media (requires Core ^1.0)
├── Categories (requires Core ^1.0)
├── Blog (requires Core ^1.0)
└── Comments (requires Core ^1.0, Blog ^1.0)
Programmatic Access
use Esegments\ModularArchitecture\Facades\Modular;
// Get modules that depend on Core
$dependents = Modular::getDependents('Core');
// Get Core's dependencies
$dependencies = Modular::getDependencies('Core');
// Check if enabling is safe
$resolver = app(DependencyResolver::class);
$result = $resolver->canEnable('Blog');
if (!$result->isValid()) {
foreach ($result->errors as $error) {
echo $error;
}
}
Circular Dependencies
Circular dependencies are automatically detected:
Module A requires B
Module B requires C
Module C requires A ← Circular!
Error:
CircularDependencyException: Circular dependency detected: A → B → C → A
Detection
The resolver uses the sweetchuck/cdd library for cycle detection.
Conflicts
Declare modules that cannot coexist:
{
"name": "NewAuth",
"conflicts": {
"LegacyAuth": "*",
"OldAuth": "^1.0"
}
}
If both modules are enabled, you’ll get:
ConflictException: Module [NewAuth] conflicts with [LegacyAuth]
Validation
Validate All Modules
php artisan modular:validate
Validate Specific Module
php artisan modular:validate Blog
Validation Checks
- Manifest validity - JSON structure, required fields
- Dependencies exist - Required modules are installed
- Version compatibility - Versions satisfy constraints
- No circular dependencies - No dependency cycles
- No conflicts - Conflicting modules not both enabled
Safe Operations
Safe to Disable?
Before disabling, check for dependents:
$dependents = Modular::getDependents('Core');
if ($dependents->isNotEmpty()) {
// Cannot safely disable - other modules depend on it
}
Safe to Remove?
$validator = app(DependencyValidator::class);
$result = $validator->canRemove('Blog');
if (!$result->isValid()) {
// Cannot remove - would break dependencies
}
Optional Dependencies
For soft dependencies (nice-to-have but not required):
// In your service provider
public function boot(): void
{
if (Modular::isEnabled('Analytics')) {
// Register analytics integration
$this->registerAnalytics();
}
}
Dependency Resolution Order
- Parse all
module.jsonfiles - Build dependency graph
- Detect cycles (fail if found)
- Topologically sort
- Return ordered collection
$resolver = app(DependencyResolver::class);
$ordered = $resolver->resolve($modules);
// $ordered is a ModuleCollection in load order