How to move a dependency to Composer while requiring an old version

Joe • January 16, 2018

day job php today i learned

A common problem I run into with older applications are dependencies that have been added and loaded from the application's repository. You would often see a "libraries" folder with a "className.php" type file. If you're lucky you'll have the entire folder of the dependency including the release notes to be able to find out exactly what version you're using. Composer lets us easily move to this to our composer.json file by adding it to our require section:

"require": {
        "somevendor/somepackage": "^1"
    },

This will give us the latest version of any 1.x release of the package. What if the author hasn't tagged our older version? Maybe they converted the repository to git from subversion or some other system? You have to go digging into the commit history to find the commit you want to match your current version. (Hopefully the author has the entire commit history in the repo.) Once you have the commit hash you can require that specific version:

"require": {
        "somevendor/somepackage": "dev-master#COMMITHASHHERE"
    },

This tells composer to use the specified commit as the version of the package. Now you can easily move the dependency to Composer at the exact version (hopefully) that you currently have in your application.

Also:

You may need to add to your composer.json file:

"minimum-stability": "dev",
    "prefer-stable": true,
    "require": {
        "somevendor/somepackage": "dev-master#COMMITHASHHERE"
    },

The minimum-stability allows you to use "dev-master" and "prefer-stable" set to "true" will prevent ALL your dependencies from using dev versions. This way you can ensure you're still getting stable packages unless you override the version.

The next step for me in this process is to usually remove the package from source control and then search the code base for usages and add the autoloader and update where the class is called from (and sometimes how the class is called). Make sure you're writing tests as you go so you can easily check if you break something. This includes Unit, Functional/Feature, and/or even Acceptance tests.

Happy Refactoring.