How to override composer package dependencies with your own git repository

So you're working on your PHP application and use a composer package that has someone else's composer package as a requirement to work, and for whatever reason you need to make a change to that required package. Maybe there's a bug in it, maybe it's not got some functionality you need.

There's a little known feature built into composer that allows you to override packages that a main package in your composer file may require, without even needing to submit your updates to satis or packagist.

This feature is called 'replace'. There are some details about how it works in the official composer documentation but they don't go nearly far enough into explaining how to use it. 

I found myself in this situation recently and managed to work out a way of doing this with minimal effort. 

Let's assume this is your composer.json file in your project. As you can see below, I'm requiring in the excellent carbon date package. In the background, this requires the symfony/translation package, but in any normal situation I wouldn't need to worry about that as it'll be automatically pulled in when composer spots it as a requirement in the carbon composer.json file.

{
    "require": {
        "nesbot/carbon": "1.21.*"
    }
}
 

So lets say I now need to make a change to the required package (symfony/translation). The first step is to fork it or clone it into it's own git repository. It doesn't really matter where this is (e.g GitHub, GitLab, Bitbucket, etc) as long as it's accessible by you remotely.

When you go to copy it, you'll need to make a couple of minor changes to it's composer.json file. The first will be the package name - you'll need to give it a unique name relating to your project. So if the name of it was previously "symfony/translation", I'd call it "rmwebs/translation" for example.

The second change is to add a 'replaces' line. This lets composer know that this package exists to override another package. Here's a cut-down copy of the symfony translation composer.json file showing the modifications that have been made:

{
    "name": "rmwebs/translation",
    "replaces": "symfony/translation",
    "type": "library",
    "description": "Symfony Translation Component",
    "keywords": [],
    "homepage": "https://symfony.com",
    "license": "MIT",

    [...]

}

Once you've made those changes, go ahead and push it up into your new git repo. You'll also want to tag it to match up with the package it's replacing.

Next, go back to your original project's composer.json file. We need to let the file know that we're wanting to pull in a composer package that isn't in a satis or packagist repository. To do this we add a repositories section. This is an array that tells composer to try to load any composer.json files from a specified location. If you're using satis you've probably already got a sections for this so just add your custom git repositories above the satis ones to have them loaded in first.

You then need to add your custom translation package to your require section to load it in, overriding the symfony/translation package.

An example of how this should look for you would be as follows:

{
    "repositories": [
        {
            "type": "git",
            "url": "https://github.com/rmwebs/translation.git"
        }
        // Any additional repos (e.g satis) go here
    ],

    "require": {
        "nesbot/carbon": "1.21.*",
        "rmwebs/translation": "2.*"
    }
}
 

That's pretty much it. It's a simple little process that'll allow you to quickly and easily override third party packages with minimal effort.


Comments