Use Composer Patches to easily fix issues in third-party code without needing to make a module.
We’ve all seen it; you find an error in someone else’s code. You’ve alerted the vendor, they promise a fix soon, but you need to fix the issue now. What do you do?
There are two ways of changing third-party code:
Today we’re going to talk about patching modules using Composer Patches.
Patches should be seen as temporary files that you want to get rid of as soon as possible. Ideally, the vendor will release the fix in a future version and you can then remove the patch. Carefully categorising your patches into folders really helps ease this process.
We like to create a patches folder in the root of the project, then have a folder for each vendor, and within this a folder for each module. This would give you a structure like this:
Before you can create a patch you need to create a checkpoint of the current version. This allows you to produce a list of all the changes (a 'diff') later on for our patch.
Go into the module folder, init a Git repository, add all existing files and do a dummy commit. This gives us a starting point, before your changes:
You now have a local repository, any changes you make now will be tracked.
Make your change in the vendor’s module as required. Remember to keep them simple, if you're doing lots of changes it's normally best to make your own module instead.
Now you've made the change you can get details of all your changes (the 'diff') using Git. Store the output of this into a patch file which we'll tell Git about next.
This creates a new patch file in our newly create patch folder. Replace patch-name with a clear descriptive name of what your patch is for.
MageWorx have an excellent Giftcard module which allows customers to purchase gift cards for friends and family and have them automatically emailed to their recipient on a set date.
Our client had an issue where in some cases the email was never sent. This caused a customer-service nightmare, we needed to get this sorted promptly.
We tracked down the fault to the way the module got the list of vouchers to send on a Cron. The data was limited to only logged in customer gift cards, meaning that guest orders would never be automatically sent.
By updating one line to use a less-restrictive function we were able to get vouchers sending again while we waited for MageWorx to implement our fix in their module.
The final step is telling Composer to automatically apply your patch when installing the module.
Composer doesn’t do this by default, and instead needs an extension to be added. There’s a couple of different options to pick from, but the de facto within the community is the excellent cweagans composer patches. To install this run:
The final step is to connect the third-party module with our patch.
Within your composer.json file look for a section called ‘extra’. It should look something like this:
If the section isn’t already in your composer.json then add it in.
Within the ‘extra’ section add a new “patches” section. Within that the syntax is simply the name of the module you wish to patch, followed by your patch, like this:
Here we are applying a patch from patches/vendor/module/patch.patch to the vendor/module.
The changes in step 5 are sufficient to apply our patch, but as you have changed composer.json directly a warning will be shown on each run as the composer.json file is out of sync with composer.lock.
Run the following to sync the files up:
The final check is to make sure this all works.
That’s it! You’ve now created a patch which will automatically apply whenever the module is installed. Remember to remove the patch once the fix is applied to the vendor’s code in the future.