How To Use Forked Repositories In Composer

How To Use Forked Repositories In Composer - Master Zend Framework

Have you ever identified a bug in a third-party repository which you’re using with Zend Framework, Zend Expressive, or another PHP-based project? I’m sure we’ve all been there at one time or another.

Why Use Forked Repositories?

Have you ever submitted a patch to a repository which your application relies on, but, because that patch is vital to the uptime of your application, you can’t wait for it to be reviewed and merged into the next release?

In times like these, it’s fair to want them to move faster than they normally would, so that you don’t have to wait for the normal review, merge, and release cycles.

However, you’re but one of many users of a library. And they’re not there solely to service our needs. Given that, just because you submit a patch doesn’t mean that they have to drop everything and merge it for us — assuming that it passes review.

But, you may urgently need the patch to be applied and released. So, what do you do? In times like these, you can use Composer’s ability to use custom repositories, specifically a fork which you create and patch.

If this sounds appealing to you — because perhaps you’re in this very situation right now — let’s now step through the process of modifying your composer.json configuration so that you can use one.

How To Configure Them

I’ll assume that you have an existing repository on GitHub; let’s assume that its URI is https://github.com/settermjd/superduper, just for argument’s sake, and that it was registered in Packagist.

Given that, you’d likely have a composer.json file that looked something like this one:

{
    "require": {
        "settermjd/superduper": "^1.0.0"
    }
}

Assuming that you have already forked and patched the relevant classes of the library, and pushed them to your fork, you now have to configure the repositories section of composer.json.

The repositories section allows you to use repositories from a variety of locations, including VCS repositories, such as Git, SVN, and Mercurial.

These can be repositories on professional hosting services, such as GitHub, Bitbucket, and Toran Proxy, or self-hosted repositories.

It also supports a number of other package types, such as Pear. But in today’s tutorial, we’re only going to focus on VCS-based packages.

When configured, these repositories are consulted before Packagist is, effectively giving them higher priority. What’s more, the repositories can be both public and private. This is quite handy if your source code needs to be kept private.

As our simplistic repository is on GitHub here’s how we’d configure the repositories section of composer.json, specifically showing how to work with a public Git repository:

{
    "require": {
        "settermjd/superduper": "^1.0.0"
    },
    "repositories": [
        {
            "type": "vcs",
            "url":  "git@github.com:mycompany/superduper.git"
        }
    ]
}

All we need to do is to add an array in the repositories section of composer.json, providing the type and url keys. When we run install or update, this repository will be searched, and if the repository is found, it will be pulled in.

{
    "require": {
        "settermjd/superduper": "^1.0.0"
    },
    "repositories": [
        {
            "type": "vcs",
            "url": "http://svn.mycompany.com/superduper/",
            "trunk-path": "Trunk",
            "branches-path": "Branches",
            "tags-path": "Tags"
        }
    ]
}

To use an SVN repository takes a little more effort, but not much. In this case, as you can see in the code above, we’ve again provided the type and url keys, as well as set three extra parameters.

These are: trunk-path, branches-path, and tags-path. These set the base prefix in the SVN repository for where these elements can be found.

If you have a custom setup, then provide these settings as suits your configuration. If you’re working with a standard Subversion installation, then you’ll likely not need to worry about them.

How To Use Private Repositories?

If the repository you’re working with is private however, then you need to put in a bit of extra effort. Git, again, is the quickest to setup.

In this case, if you have your SSH public key listed on the remote Git repository, then you don’t need to add any particular credentials. This will be used during the install and update process taking care of your authentication needs.

However, if you’re working with SVN, then you may have a bit more work to do; but not much. In this case, let’s say that your SVN server’s setup to use HTTP Basic authentication, and that you’re using the following credentials:

  • username: my-username
  • password: 12345

In that case, you’ll need to add the http-basic section to your composer.json. Have a look at the following example and let’s step through it.

{
    "http-basic": {
        "svn.example.org": {
            "username": "username",
            "password": "password"
        }
    }
}

Inside the http-basic section is another key/value pair. The key is the hostname of the SVN server that you need to authenticate against.

The value is an array which contains the authentication credentials, specifically the username and password. With that in place, you’re now able to connect to a private SVN repository.

How To Use Local Files?

If you’re working with a locally cloned copy of the code, then this might be the simplest path for you to follow. I’m including it at the end, because I’m assuming that you’d be following the usual Fork -> Patch -> PR cycle.

But that may not always be the case. If so, here’s how to use a local copy of a repository. In that case, you’ll need to set the type to path and the url to the path on your local filesystem, where the library has been cloned, such as in the example below.

{
    "require": {
        "settermjd/superduper": "^1.0.0"
    },
    "repositories": [
        {
            "type": "path",
            "url": "/opt/mycompany/superduper"
        }
    ]
}

In this case, the library has been cloned to /opt/mycompany/superduper on my development machine. At this point, you may be wondering how the Composer determines the package version? Here’s the official word from the Composer documentation:

If the package is a local VCS repository, the version may be inferred by the branch or tag that is currently checked out. Otherwise, the version should be explicitly defined in the package's composer.json file. If the version cannot be resolved by these means, it is assumed to be dev-master.

In Conclusion (tl;dr)

While this wasn’t a long post, I hope that it helps you, if you’re in the position where you urgently need to use a custom copy of a repository.

There’s a lot more on offer, and I strongly encourage you to consult the repositories section of the documentation to learn more.

And this brings us to the end of the series. If there’s anything that you’re uncertain about, ask a question in the comments, or consult the relevant section of the documentation.

Composer’s an amazing tool, one which has immeasurably improved the quality of the PHP ecosystem. Make sure you make the most out of it.

Further Reading



About Matthew

Matthew Setter Matthew Setter is a PHP & Zend Framework specialist. If you're in need of a custom software application, need to migrate an existing legacy application, or want to know your current application's GPA - get in touch.