Using composer patches

February 3rd, 2021

When you use software that is open source, you'll sometimes run into issues or small bugs that have already been fixed by the community in a PR or an issue, but have yet to be merged and/or released. If you're impatient and need that fix now, composer patches can be a solution for this problem.

Using composer patches

You can start using composer packages by installing the cweagans/composer-patches composer package.

composer require cweagans/composer-patches

Once this is installed, you can configure it inside your composer.json file under the extra key. But before we can do that, you need a patch to apply!

Getting a patch to apply

The easiest way to get a patch is by getting it from a pull request on Github. Github allows you to download a .diff or .patch file (both are supported by the composer plugin) by requesting the page of the pull request, followed by the file extension. For example:

https://github.com/spatie/ray/pull/266 can be downloaded as a .diff by visiting https://github.com/spatie/ray/pull/266.diff

The PR above looks like this:

diff --git a/src/Ray.php b/src/Ray.php
index 0c94673..6d1a080 100644
--- a/src/Ray.php
+++ b/src/Ray.php
@@ -94,14 +94,14 @@ public function newScreen(string $name = ''): self
         return $this->sendRequest($payload);
     }
 
-    public function clearAll()
+    public function clearAll(): self
     {
         $payload = new ClearAllPayload();
 
         return $this->sendRequest($payload);
     }
 
-    public function clearScreen()
+    public function clearScreen(): self
     {
         return $this->newScreen();
     }
@@ -271,7 +271,7 @@ public function image(string $location): self
         return $this->sendRequest($payload);
     }
 
-    public function die($status = '')
+    public function die($status = ''): void
     {
         die($status);
     }
@@ -413,7 +413,7 @@ public function pause(): self
         return $this;
     }
 
-    public function html(string $html = '')
+    public function html(string $html = ''): self
     {
         $payload = new HtmlPayload($html);

Configuring your patch

Once you have the patch file, you can add it to a folder inside your project and configure the patch to be applied. I use <project-root>/patches.

Inside the extra key of your composer.json you can configure all patches

"extra": {
    "patches": {
        "spatie/ray": {
            "Add missing return types": "patches/github-pr-266.diff",
        }
    }
},

This tells the composer-patch plugin to patch the spatie/ray package using the patches/github-pr-266.diff file. Every time you now run composer install or composer update, the plugin will re-fetch the package from packagist, and re-apply your patches to it.

Your composer output will contain something along the following:

Removing package some/package so that it can be re-installed and re-patched.
  - Removing spatie/ray (v1.18)
  
...

Gathering patches for root package.
Gathering patches for dependencies. This might take a minute.

...

- Applying patches for spatie/ray
  patches/github-pr-266.diff (Add missing return types)

If a patch fails, composer will skip the patch and continue by default. If you would like it to fail instead, you can configure it by adding "composer-exit-on-patch-failure": true to the extra key in your composer.json.

Once the PR you need is merged and released, the patch won't do anything anymore and you're free to delete it.

You can like or retweet this Tweet
MENU