LoginSignup
0
1

More than 3 years have passed since last update.

Patching a PHP Composer Package without forking

Last updated at Posted at 2019-06-29

Sometimes in the course of our work on PHP projects, we may encounter situations such as a PHP Package having bugs or issues that we need urgently fixed.

When that happens what usually occur is 1 of the following 3:

  1. Edit the files in the vendor folder directly and commit the huge vendor folder
  2. Fork the package and link to the your forked version in composer.json while making a pull request to the original package, hoping the original authors merge your PR soon enough so you don't have to continue maintaining your forked version.
  3. If the web framework you uses support dependency injection, you try to swap the library class with a class of your own via the service container.

However as you may have guessed, many of us would like to avoid approach 1 and 2. Approach 3 while ideal may not be always possible. Having said that there are times where approach 1 and 2 are great too.

So are there other approaches? One that would allow you to patch the official package while allowing you to receive updates to the package in other areas as you wait for your PR to merge?

Composer Patches Packages

I believe the answer lies in composer-patches packages. In a nutshell, how composer-patches works is by applying your patch after the package is installed or updated (After you ran composer install and composer update

In the PHP ecosystem, these 2 packages are the most popular

Let's have a demo of how to use each

cweagans/composer-patches

  • Fork the package, create a branch, commit and push your fixes
  • Make a pull request to the original package
  • While waiting for the package maintainer to merge your changes
  • Go to the commit you make and append .patch or .diff to the end of it.

It will look something like this

https://github.com/Laravel-Backpack/CRUD/commit/c474aa4cdc7616ccd9e68e6e823c6d71b2d5a2cb.diff

https://github.com/Laravel-Backpack/CRUD/commit/c474aa4cdc7616ccd9e68e6e823c6d71b2d5a2cb.patch
  • composer require cweagans/composer-patches
  • Add an "extra" key to composer.json with the following
"extra": {
    "patches": {
      "laravel-Backpack/CRUD": {
        "Fix for url generation after save_and_edit": "https://github.com/Laravel-Backpack/CRUD/commit/4521d21ee852061421e403a819fbfca582fa27df.diff"
      }
    }
  }

If you need to add more patches to the same package, Add more key-value pairs under the patches section. For the value, it need not be a github link, it can be a local path in your project as well. As long as it is a diff or patch file.

Now when you run composer update/install, Your patch will be run after the package is installed or updated. Allowing you to continue to get updates to the packages in other parts of the package codebase. And when your PR gets merged, you simply just need to remove your patches entries for that package

vaimo/composer-patches

vaimo/composer-patches as an alternative, allows you to specify the version constraints the patch should apply to. Here is an example:

After composer require vaimo/composer-patches, you can do this:

Example below copied from the package readme

{
  "extra": {
    "patches": {
      "some/package": {
        "having two patches for same fix": {
          ">=1.0.0 <1.2.0": "some/path/legacy.patch",
          ">=1.2.0": "some/path/current.patch"
        }
      },
      "some/other-package": {
        "same done for extended patch declaration format": {
          "source": {
            ">=1.0.0 <1.2.0": "some/path/legacy.patch",
            ">=1.2.0": "some/path/current.patch"
          }
        }
      }
    }
  }
}

Hope this helps and give you more confidence in using many of the good open source packages out there.

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1