This document explains the different update scenarios that Composer Update Helper currently handles, and identifies scenarios that are not yet fully supported.
Scenario: A package has a newer version available that is compatible with all current dependencies.
Example:
- Installed:
vendor/package:1.2.0 - Latest:
vendor/package:1.3.0 - Result: ✅ Update suggested
Handling: The system compares installed version with latest version and suggests update if newer.
Scenario: A package update is blocked because another installed package requires an older version.
Example:
- Trying to update:
rector/rector:2.3.1 - Blocked by:
lexik/jwt-authentication-bundlerequiresrector/rector ^1.2 - Result:
⚠️ System checks iflexik/jwt-authentication-bundlehas a newer version that supportsrector/rector:2.3.1- If newer compatible version found: ✅ Suggests updating both packages together
- If not found: ❌ Update filtered with clear message:
lexik/jwt-authentication-bundle requires rector/rector ^1.2
Handling:
- The system checks
composer.lockfor all packages that depend on the target package - Verifies if the proposed version satisfies all dependent constraints
- NEW: If not satisfied, automatically checks if dependent packages have newer versions that support the proposed update
- If compatible dependent version found, suggests updating both packages together
- If not found, the update is filtered and the conflicting dependent is reported
- Example: When
zircote/swagger-php:6.0.2conflicts withnelmio/api-doc-bundlerequiring^4.11.1 || ^5.0, the system checks ifnelmio/api-doc-bundle:6.0.0exists and requireszircote/swagger-php:^6.0- If found: Suggests
composer require --with-all-dependencies zircote/swagger-php:6.0.2 nelmio/api-doc-bundle:6.0.0
- If found: Suggests
Status: ✅ Fully supported with automatic dependent package update detection
Scenario: A package update requires a newer version of a transitive dependency that is not installed or is outdated.
Example:
- Trying to update:
scheb/2fa-google-authenticator:8.2.0 - Requires:
spomky-labs/otphp:^11.4 - Installed:
spomky-labs/otphp:11.3.0 - Result:
⚠️ Update filtered, transitive dependency suggested
Handling:
- The system checks all requirements of the proposed package version
- Verifies if installed versions satisfy those requirements
- If not satisfied, suggests updating the transitive dependency
- Generates a command that includes both packages
Status: ✅ Fully supported with transitive dependency suggestions
Scenario: A package requires another package at the exact same version (e.g., self.version constraint).
Example:
- Trying to update:
scheb/2fa-google-authenticator:8.2.0 - Requires:
scheb/2fa-bundle: self.version(means version 8.2.0) - Installed:
scheb/2fa-bundle:8.1.0 - Result:
⚠️ Update filtered, suggests updatingscheb/2fa-bundle:8.2.0together
Handling:
- Detects
self.versionor@selfconstraints - Extracts the required version from the proposing package version
- Suggests updating the related package to match the version
- Includes both packages in the same update command
Status: ✅ Fully supported
Scenario: A package update would exceed the framework version constraint (e.g., Symfony 7.4.* constraint).
Example:
- Framework constraint:
symfony:7.4.* - Trying to update:
symfony/console:8.0.0 - Result: ✅ Update limited to
symfony/console:7.4.x(latest in 7.4.* range)
Handling:
- Detects framework constraints from
composer.json(extra.symfony.require) or installed core packages - Limits package updates to versions compatible with the framework constraint
- Supported frameworks: Symfony, Laravel, Yii, CakePHP, Laminas, CodeIgniter, Slim
Status: ✅ Fully supported for major frameworks
Scenario: User explicitly ignores certain packages from updates via configuration.
Example:
ignore:
- doctrine/orm
- symfony/security-bundleHandling:
- Packages in the
ignorelist are excluded from update suggestions - Still shown in output with available versions for information
- Configuration supports both
.yamland.ymlextensions
Status: ✅ Fully supported
Scenario: User wants to force-include packages even if they are in the ignore list.
Example:
ignore:
- symfony/*
include:
- symfony/security-bundle # Override ignore for this specific packageHandling:
includesection has priority overignoresection- Allows fine-grained control: ignore framework packages but include specific ones
Status: ✅ Fully supported
Scenario: Separating production and development dependency updates.
Example:
- Production:
symfony/console:7.4.0 - Development:
phpunit/phpunit:12.5.5
Handling:
- Automatically categorizes packages as
(prod)or(dev) - Generates separate commands:
composer requirevscomposer require --dev - Maintains proper dependency separation
Status: ✅ Fully supported
Scenario: Preventing suggestions for packages already at or above the target version.
Example:
- Installed:
vendor/package:2.0.0 - Latest:
vendor/package:2.0.0(or1.9.0) - Result: ✅ No update suggested
Handling:
- Compares installed version with proposed version
- Skips if installed >= proposed version
- Only suggests actual updates
Status: ✅ Fully supported
Scenario: A package update requires updating multiple transitive dependencies.
Example:
- Trying to update:
scheb/2fa-bundle:8.2.0 - Requires:
scheb/2fa-email:8.2.0(self.version) - Requires:
spomky-labs/otphp:^11.4 - Result:
⚠️ Suggests updating all three packages together
Handling:
- Collects all required transitive updates
- Groups them by production/dev
- Generates commands that include all related packages
- Ensures all dependencies are updated together
Status: ✅ Fully supported
Scenario: Analyzing the impact of updating packages when conflicts are detected (which packages would be affected).
Example:
- Updating
package-ato2.0conflicts withdependency-xwhich requires^1.5 - The analysis shows that
dependent-package-1anddependent-package-2would be affected - Transitive packages that depend on these affected packages are also identified
Handling:
- Automatically analyzes which packages would be affected by updating a conflicting package
- Shows direct affected packages (packages that directly depend on the conflicting package)
- Shows transitive affected packages (packages that depend on directly affected packages)
- Displays impact analysis in output with clear formatting
- Provides complete dependency chain visualization
Implementation Details:
- Uses
ImpactAnalyzer::analyzeImpact()to analyze impact when conflicts are detected - Recursively checks transitive dependencies (up to 5 levels deep to prevent infinite loops)
- Format:
📊 Impact analysis: Updating package-a to 2.0 would affect: - dependent-package-1 (requires package-a:^1.5) - Integrated into conflict detection flow
Status: ✅ Fully supported
Scenario: Package versions with wildcards (e.g., 7.4.*, ^8.0, ~1.2).
Example:
- Framework constraint:
symfony:7.4.* - Latest version:
symfony/console:7.4.3
Handling:
- ✅ Framework constraints with wildcards are supported
- ✅ Dependency checking now supports wildcard constraints (
*,^,~) - ✅ Full dependency conflict detection for wildcard constraints using
versionSatisfiesConstraint
Status: ✅ Fully supported
The following scenarios are documented but not yet implemented. When these cases occur, the tool will:
- ❌ Filter packages showing conflict messages
- ❌ Not provide automatic solutions - Requires manual intervention from the user
⚠️ Limited guidance - User must analyze and resolve conflicts manually
Each case below explains what happens currently, what's missing, and what manual steps the user must take.
Scenario: Package A requires Package B at version X, while Package B requires Package A at version Y.
Example:
vendor/package-a:2.0requiresvendor/package-b:^1.5vendor/package-b:1.6requiresvendor/package-a:^2.1- Result: ❌ No solution provided - Both packages filtered separately without recognizing the circular dependency
Current Behavior:
- Each package would be filtered individually with separate conflict messages
- ❌ No recognition of the circular nature of the conflict
- ❌ No suggestion to update both packages together
- ❌ No strategy to break the circular dependency
What's Needed:
- Detection of circular dependencies
- Resolution strategies (update both together, or suggest breaking the circular dependency)
- Warning messages explaining the circular nature
Priority: Medium
Current Solution: Manual intervention required - user must analyze conflicts and update packages manually
Scenario: A conflict chain where Package A → B → C → D, and updating D requires updating C, B, and A.
Example:
- Update
package-d:4.0requirespackage-c:^3.0 - Update
package-c:3.0requirespackage-b:^2.0 - Update
package-b:2.0requirespackage-a:^1.5 - All are currently at older versions
Current Behavior:
- ✅ Transitive dependencies are suggested (one level deep)
⚠️ Partial solution - Only immediate transitive dependencies are suggested- ❌ No automatic detection of the full chain depth (A → B → C → D)
- ❌ No optimization to update all packages in the chain at once
- ❌ No visualization of the complete dependency chain
What's Needed:
- Recursive traversal to detect full dependency chains
- Optimized command generation for multi-level chains
- Better visualization of dependency chains
Priority: Medium-High
Current Solution: User must manually execute commands multiple times, one level at a time
Scenario: A package is abandoned and conflicts with newer versions of dependencies, but no compatible version exists.
Example:
abandoned/package:1.0.0requiresold/dependency:^2.0old/dependencyis at version 5.0.0, no longer supports ^2.0abandoned/packagehas no newer version
Current Behavior:
- ✅ Detection implemented - Package abandonment status is detected via Packagist API
- ✅ Warning shown - Update is filtered with conflict message AND abandoned warning
- ✅ Replacement suggested - If Packagist provides a replacement, it's shown in the warning
⚠️ Partial solution - Warning is shown but no automatic migration path- ❌ No migration path recommendations beyond replacement suggestion
Implementation Details:
- Uses Packagist API (
packagist.org/packages/{package}.json) to checkabandonedfield - Warning format:
(⚠️ Package is abandoned, replaced by: new-package/name)if replacement exists - Warning format:
(⚠️ Package is abandoned)if no replacement is specified - Integrated into conflict detection flow
What's Still Needed:
- Migration path recommendations (step-by-step guide)
- Automated replacement suggestions (beyond Packagist's replacement field)
- Alternative package discovery
Priority: Low-Medium (Partially implemented ✅)
Current Solution: ✅ Automatic detection and warning - user can see replacement package if available
Scenario: Conflicts that only exist in private repositories or specific repository configurations.
Current Behavior:
- ✅ Basic support for any Composer repository
- ❌ No solution provided - Conflicts from repository priorities are not detected
- ❌ No special handling for repository-specific constraints
- ❌ No detection of repository priority conflicts
What's Needed:
- Better support for repository-specific version constraints
- Detection of conflicts between repositories
- Suggestions when conflicts might be resolved by adjusting repository priorities
Priority: Low
Current Solution: Manual intervention - user must adjust repository priorities in composer.json
Scenario: Optimizing multiple package updates to minimize dependency resolution steps.
Example:
- 10 packages need updates
- Some updates depend on others
- Optimal strategy: group updates to minimize resolver runs
Current Behavior:
- ✅ Suggests all compatible updates together (basic grouping)
⚠️ Suboptimal solution - All packages in one command may be inefficient- ❌ No optimization for update order
- ❌ No batching strategy to minimize resolver calls
- ❌ No analysis of dependency graph to optimize execution
What's Needed:
- Dependency graph analysis
- Optimal update ordering algorithm
- Batching strategy to group updates efficiently
Priority: Medium
Current Solution: Works but may be slower - all packages updated in one command regardless of dependencies
Scenario: Predicting conflicts before actually running composer require, using dry-run or simulation.
Current Behavior:
- ✅ Uses
composer showto check package requirements (good approximation) ⚠️ Partial solution - May miss edge cases that only appear during actual resolution- ❌ No actual dry-run of
composer require - ❌ Some conflicts may only be detected when Composer actually resolves dependencies
- ❌ False positives/negatives possible
What's Needed:
- Integration with Composer's dependency resolver
- Dry-run simulation of updates (
composer require --dry-run) - More accurate conflict prediction
Priority: High (would improve accuracy significantly)
Current Solution: Good approximation but not 100% accurate - some conflicts may only appear during actual composer require
Scenario: When a package update is blocked by conflicts, suggest alternative packages that might work.
Example:
package-a:2.0conflicts withdependency-x- Alternative
package-b:2.0might work withdependency-x
Current Behavior:
- ✅ Alternative package detection - Now implemented
- Automatically searches for alternative packages when conflicts exist
- Uses Packagist API to find similar packages based on keywords
- Shows alternatives when packages are abandoned without replacement
- Shows alternatives when no fallback version is available
- Example:
💡 Alternative packages: - new-package/name (recommended replacement) - alternative/pkg (similar functionality)
- ✅ Migration path suggestions via Packagist API search
- ✅ Package discovery functionality
Implementation Details:
AlternativePackageFinder::findAlternatives()function searches for alternatives- Checks abandoned status first (if abandoned with replacement, shows replacement)
- Searches Packagist for similar packages using keywords extracted from package name
- Returns top 3 most relevant alternatives
- Output includes alternative packages section when available
What's Still Needed:
- Cost-benefit analysis of alternatives
- Version compatibility checking for alternatives
- Migration guide generation
Priority: Low (Partially implemented ✅)
Current Solution: ✅ Alternative packages are automatically suggested when conflicts exist
Scenario: Providing multiple resolution strategies when conflicts are detected.
Example:
- Conflict:
package-a:2.0conflicts withdependency-x:1.0 - Strategy 1: Update
dependency-xto2.0(if compatible) ✅ Supported - Strategy 2: Keep
package-a:1.9(if compatible withdependency-x:1.0) ✅ Now supported - Strategy 3: Remove
dependency-x(if not critical) ❌ Not supported
Current Behavior:
- ✅ Suggests transitive dependency updates (Strategy 1) - Implemented
- ✅ Dependent package update detection (Strategy 1b) - Now implemented
- When a package conflicts with a dependent package, automatically checks if the dependent package has a newer version that supports the proposed update
- If found, suggests updating both packages together
- Example:
composer require --with-all-dependencies package-a:2.0 dependent-package:3.0
- ✅ Fallback version suggestions (Strategy 2) - Implemented
- Automatically searches for compatible older versions when primary update conflicts
- Verifies fallback versions satisfy all conflicting dependencies
- Shows "Alternative solutions" section in output
- Example:
💡 Alternative solutions: - package-a:1.9.5 (compatible with conflicting dependencies)
- ❌ No dependency removal suggestions (Strategy 3)
⚠️ Partial implementation - Three strategies available (transitive updates, dependent updates, fallback versions), removal suggestions still missing
Implementation Details:
VersionResolver::findCompatibleDependentVersions()searches for newer versions of conflicting dependent packages- Checks if dependent packages have versions that support the proposed update
- If found, adds them to transitive updates to be included in the same command
findFallbackVersion()function searches for compatible older versions- Verifies fallback satisfies all conflicting constraints
- Verifies fallback's own requirements don't conflict with installed packages
- Output includes both dependent updates and fallback suggestions when available
What's Still Needed:
- Dependency removal suggestions (Strategy 3)
- Multiple strategy comparison
- User choice of preferred strategy
Priority: Medium-High (Partially implemented ✅)
Current Solution: ✅ Three strategies available - transitive updates, dependent package updates, and fallback versions
Scenario: A package update conflicts with dependent packages, but no compatible versions of the dependent packages exist that support the proposed update.
Example Cases:
-
zircote/swagger-php:6.0.2conflicts withnelmio/api-doc-bundlerequiring^4.11.1 || ^5.0- No version of
nelmio/api-doc-bundleexists that supportszircote/swagger-php:^6.0 - All available versions (up to 5.9.2) require
^4.11.1 || ^5.0
- No version of
-
phpdocumentor/reflection-docblock:6.0.1conflicts witha2lix/auto-form-bundle:1.0.0requiring^5.6- No version of
a2lix/auto-form-bundleexists that supportsphpdocumentor/reflection-docblock:^6.0 - Latest version (1.0.0) requires
^5.6
- No version of
Current Behavior:
- ✅ System automatically searches for compatible versions of dependent packages
- ✅ System checks all available versions of conflicting dependents
- ✅ If no compatible versions found, explains why no automatic solution is available
- ✅ Suggests fallback versions of the original package (if available)
- ✅ Suggests alternative packages (if available)
- ✅ Provides maintainer contact information for manual resolution
What Happens:
- System detects conflict with dependent package
- System searches for newer versions of dependent package that support the proposed update
- If no compatible versions found:
- Package is filtered (not included in update commands)
- Clear explanation is shown: "No compatible version of {dependent-package} found that supports {package}:{version}"
- Fallback version suggestions are shown (if available)
- Alternative package suggestions are shown (if available)
- Maintainer contact information is provided (if available)
Output Example:
⚠️ Filtered by dependency conflicts:
- zircote/swagger-php:6.0.2 (prod) (conflicts with 1 package: nelmio/api-doc-bundle requires zircote/swagger-php ^4.11.1 || ^5.0)
ℹ️ No compatible version of nelmio/api-doc-bundle found that supports zircote/swagger-php:6.0.2
ℹ️ All available versions of nelmio/api-doc-bundle require zircote/swagger-php:^4.11.1 || ^5.0
💡 Alternative solutions:
- zircote/swagger-php:5.7.8 (compatible with conflicting dependencies)
💡 Alternative packages:
- [alternative suggestions if available]
📧 Contact maintainers:
- [maintainer contact information if available]
Why This Happens:
- Package maintainers haven't released versions that support the newer dependency versions yet
- Breaking changes in the dependency require significant updates to the dependent package
- Dependent package may be abandoned or in maintenance mode
- Version compatibility matrix hasn't been updated by maintainers
What You Can Do:
- Use fallback versions: Use the suggested fallback version of the original package (e.g.,
zircote/swagger-php:5.7.8instead of6.0.2) - Wait for updates: Monitor the dependent package for new releases that support the newer version
- Contact maintainers: Use the provided contact information to request compatibility updates
- Consider alternatives: Evaluate alternative packages that may have better compatibility
- Manual resolution: Manually update dependencies if you have the resources to handle potential breaking changes
Status: ✅ Fully supported with clear explanations and actionable suggestions
Priority: High (User experience improvement)
- Basic package updates
- Dependent package constraint conflicts
- Package requirement conflicts
- Self-version constraints
- Framework version constraints
- Ignored packages
- Force-included packages
- Production vs development dependencies
- Version comparison to avoid unnecessary updates
- Multiple transitive dependencies
- Wildcard version constraints (dependency checking for
*,^,~constraints) - Abandoned package detection (with warnings and replacement suggestions)
- Alternative package suggestions (automatic detection and suggestions when conflicts exist)
- Maintainer contact suggestions (automatic detection and actionable steps when no automatic solution is available)
- Conflict impact analysis (automatic analysis of which packages would be affected by resolving conflicts)
- Abandoned package conflicts - Detection and warnings ✅, migration paths ✅ (alternative packages, maintainer contact)
- Conflict resolution strategies - Transitive updates ✅, fallback versions ✅, removal suggestions ❌
❌ No automatic solution provided - requires manual intervention:
- Circular dependency conflicts - No detection or resolution strategy
- Cascading conflict chains - Only one-level deep (optimization needed)
- Repository-specific conflicts - No repository priority conflict detection
- Batch update optimization - No update order optimization (suboptimal)
- Pre-installation conflict prediction - Approximate only (needs Composer resolver)
- Pre-installation conflict prediction (#17): Would significantly improve accuracy by using Composer's resolver
- Cascading conflict chains (#13): Better handling of deep dependency chains
- Conflict resolution strategies (#19): Multiple strategies for better user experience
- Batch update optimization (#16): More efficient update commands
- Wildcard constraints dependency checking (#11): Complete the partial support
- Circular dependency conflicts (#12): Less common but useful
- Abandoned package conflicts (#14): Edge case (partially supported with alternative packages)
- Repository-specific conflicts (#15): Edge case
To ensure comprehensive coverage, test cases should be created for:
- ✅ All currently supported cases (10 cases)
⚠️ Edge cases in partially supported scenarios- 📝 Mock/test scenarios for not-yet-supported cases (for future development)
Some scenarios cannot be resolved automatically and require contacting package maintainers to request dependency updates:
-
Incompatible Version Requirements
- Two packages require incompatible versions of the same dependency
- Example: Package A requires
dependency-x:^1.0, Package B requiresdependency-x:^2.0 - No version satisfies both constraints
- Action: Contact maintainer(s) of Package A or B to update their version constraints
-
Stale Packages
- Package hasn't been updated in >2 years
- Requires very old dependencies (e.g., Symfony 2.x when 6.x is available)
- Action: Contact maintainer to request dependency updates or find alternative package
-
Abandoned Packages Without Replacement
- Package is marked as abandoned
- No replacement package is suggested
- Action: Contact original maintainer or search for community fork
-
Conflicting Major Versions
- Constraints on different major versions with no overlap
- Example: Package A allows
^1.0|^2.0, Package B requires^3.0 - Action: Contact maintainer(s) to update version constraints
Current Behavior:
- ✅ Maintainer contact suggestions - Now implemented
- Automatically detects scenarios where manual intervention is needed
- Extracts maintainer information from Packagist API (name, email, homepage)
- Generates repository issue URLs for GitHub, GitLab, and Bitbucket
- Detects stale packages (>2 years without updates)
- Provides actionable steps for manual resolution
- Example:
⚠️ No automatic solution available - Contact package maintainer(s): John Doe (john@example.com)
- ✅ Automatic detection of incompatible constraints and major version conflicts
- ✅ Stale package warnings with actionable suggestions
Implementation Details:
MaintainerContactFinder::getMaintainerInfo()function extracts maintainer informationMaintainerContactFinder::shouldSuggestContact()determines when to suggest contactMaintainerContactFinder::generateIssueUrl()creates repository issue URLs- Output includes maintainer contact section when no automatic solution is available
For a detailed action plan to implement the not-yet-supported cases, ordered by complexity and feasibility, see Implementation Roadmap.
Translation Support:
- 31 languages fully supported
- See CONFIGURATION.md for complete language list and configuration
- See I18N_STRATEGY.md for translation implementation details
Last updated: 2026-01-16 Document version: 1.0