Actually, you are in a mess, but you are half way out of this mess already without seeing.
What's bad about your situation is that your modules potentially CAN depend on incompatible third party libraries. You mention they use semantic versioning, but this only covers upwards compatibility, like "minor version increases if a new feature gets added in a compatible way to the older version". Which means that this newer version is not backwards compatible!
Assume module A is using version 1.0.7 of a library, and module B is using version 1.2.5. That library got a new method added to a class in version 1.2, and module B is using that method. Can module B run with the class version 1.0.7 of module A? Of course not. You want both modules to run with the highest compatible version for both modules, 1.2.5.
How to get this? Use only one Composer autoloader and only one central dependency definition.
If you could create a composer.json
file that contains the dependencies for all the modules A, B and C, and each module states it's dependencies on other libraries, Composer would collect all these libraries, calculate the "best" usable version from it, and create an autoloader that would unambiguously load these libraries only.
Added benefit: Only one version per library without duplicates. Only one autoloader object with global knowledge about all available classes (which could optimize autoloading a bit).
And you are half way there. Each of your modules must already have a local composer.json
which states the version requirements. Do add a definition for autoloading that module itself, and give it a name. You can then reference that name in the central composer.json
(you'd probably need to add the repositories if they are private), and you are almost done. Maybe there is some fiddling with paths if you really need these modules in a defined path.
But that's about it.
And then you solve one other thing: What if module A needs some small part of module B? With Composer you can state that dependency together with all the libraries, and even if you forget to install module B, Composer would do it for you, or remind you about it.