How to solve two packages requirements conflicts when running composer install?

Solution 1:

The basic problem here is the use of branches (dev-master) instead of tagged versions. Using branches is very likely to end in problems. I am watching the Composer questions on Stackoverflow, and every time someone reports trouble with packages, they are using development branches and "minimum-stability:dev" 99% of the time.

What's happening? I must assume that you want to install these packages for the first time. So Composer does not install, but update the packages. Otherwise a working set of versions that are able to fulfill all version requirements would have been recorded in the composer.lock.

So here is the dependency situation: Two packages depend on a third package, but these two require incompatible versions.

Can you fix it? There is only one tool in the local composer.json file that will be able to allow installing the third package: Installing it with an inline version alias.

"require": {
    "anahkiasen/former": "dev-master",
    "vespakoen/menu": "dev-master",
    "anahkiasen/html-object": "dev-master as 1.1.2" /* add this line */
}

By installing the dev-master branch and declare it to be like version 1.1.2, Composer can resolve the dependencies of both packages.

The problem with this is that it will fail the very moment you have three packages depending on a fourth - in three different versions.

The correct thing would be for every development branch to include a branch-alias declaration in THEIR composer.json, which will allow Composer to detect that the dev-master branch actually is equivalent to version 1.1.x, which might have helped here (but not if any package explicitly requires a given version number - 1.1.x is not 1.1.2). Adding branch aliases still is a good thing and should be done. If a maintainer wants to avoid the constant maintenance of this hardcoded version alias in composer.json, they can alternatively develop that version in a branch that bears that .x version in their name (i.e. "v1.1.x" or "1.1.x" would be detected by Composer to contain said version in development stability).

Note that the problem I described in the last paragraph is that packages explicitly require a given version number. With this approach, if you require such a package, you cannot use an different version of that depended package yourself or in a different package. While there might be cases for requiring only one version, the better solution is to require version ranges.

My personal preference is to use the caret operator for versions greater than 1.0: ^1.1.7 would require 1.1.7 as the minimum version, but would not update to any version 2.0.0, which is considered having incompatible changes. If a package is carefully tagged with new version according to semantic versioning, this works like a charm. You'd never be surprised by incompatible changes (unless of course human nature interferes, but you should be able to detect this failure and roll back the update if your software breaks).

For versions below 1.0, note that the caret operator works different from the tilde operator - refer to the manual for more details. I do prefer tilde for packages under my control that were tagged 0.x in order to get "compatible" feature updates even if semantic versioning allows incompatible updates in the 0.x range.

But even without semantic versioning, every little bit of inaccuracy in the version number helps, like defining 1.1.* (supposedly will update to all upcoming bugfix releases) or >=1.1.2,<1.2.5.

The worst things of all is requiring "dev-master". While this is indeed very inaccurate (it will resolve to any possible commit in the branch, depending on the time you update), the problem is that you cannot go back to a previous version of "dev-master" unless you know exactly which commit id you need and add this requirement to composer.json. But then you are in exactly the same situation as above requiring an exact version (a git tag is just a named alias for a commit id).