قالب وردپرس درنا توس
Home / Tips and Tricks / How to Apply Your Own Patches to Composer Packages – CloudSavvy IT

How to Apply Your Own Patches to Composer Packages – CloudSavvy IT



PHP logo

Using third-party packages can speed up the development of your project. Sometimes you may need to add extra functionality or fix a critical bug. Here’s how to apply patches to PHP packages installed by Composer.

When to patch a package

First consider whether it is appropriate to create an in-project patch. A patch should always be a minor change. If you need to add extensive new functionality, you must open a problem with the package or split it yourself. This will help avoid conflict as the pack evolves.

You need to think carefully if the change you need is really specific to your project. Dependency patches typically affect just a few lines of code. They fix bugs and problems that would otherwise prevent you from using the package. Most patches are short-lived. They must later be replaced with fixes at the source in the package codebase.

Ultimately, you need to measure your intentions. Are you addressing an immediate issue with a package, or are you extending the package̵

7;s functionality to match your codebase? If it is the latter, you should consider contributing to the package or packing it with additional classes and features that are first-class citizens in your project.

Create a Composer patch

Once you’ve called to patch, you can start preparing your project. Composer doesn’t have built-in patch support, so we’ll cover the popular one simplify/vendor-patches project to add it. This provides an intuitive interface cweagans/composer-patches to help you create new patches.

composer require --dev symplify/vendor-patches

Make sure the package you need to patch is installed in your project:

composer require example/broken-package

Then open the problematic file in your code editor. You will find it in it vendor directory. In our example we need to edit vendor/example/broken-package/src/Broken.php:


 
class Broken {
    public function __construct(string|int $foo) {
        if (is_string($foo)) {
            echo "Valid value!";
        }
    }
}
 
?>

The Broken class is supposed to accept both strings and integers, using PHP 8’s union types. If you look at the source it unfortunately turns out that it really only accepts strings.

In our fictional example, the package manager has acknowledged the problem, but has not yet created a new release. In the meantime, let’s get around the problem.

Copy the broken file, unchanged, and add a .old suffix:

cp vendor/example/broken-project/src/Broken.php vendor/example/broken-project/src/Broken.php.old

Make sure to check it out .old File!

Then edit it original file so that it functions correctly in your codebase. While you are editing on site, the changes will take effect immediately. Check if your codebase is now behaving as expected.


 
class Broken {
    public function __construct(string|int $foo) {
        if (is_string($foo)) {
            echo "Valid value!";
        }
        else if (is_int($foo)) {
            echo "Also valid!";
        }
    }
}
 
?>

Create the patch file

You can now use the symplify/vendor-patches project to create a patch file for your fix. The package offers one vendor-patches binary file that automatically converts your vendor directory to find the changes you made.

vendor/bin/vendor-patches generate

Running the command will generate a diff for you. It is stored in it patches directory in the root of your project. The difference is calculated by the .php and .php.old files you have created.

You can run the command again to discover new patches that you add. Each modified file gets its own patch within the patches directory.

Automatic patching

Within you composer.json file, you will see a new section added:

{
    "extra": {
        "patches": {
            "example/broken-package": [
                "patches/example-broken-package-src-broken-php.patch"
            ]
        }
    }
}

The patches object maps the names of installed packages to a set of patch files to apply. These patches are applied automatically whenever you want composer install.

An installation script is registered by simplify/vendor-patches. It is called after each dependency is installed. The script checks if patches have been defined for the package. It automatically applies all found items.

You see lines in it composer install output indicating when patches were applied. If an error is reported, you can composer install --verbose for more information on why the patch was skipped. This is often because a package update fixes the problem you have patched, making your patch file redundant.

Delete patches

You can temporarily remove a patch by removing its line from composer.json. This ensures that the patch is no longer applied composer install.

To permanently remove a patch from your project, delete it composer.json line. You can then be .patch file of your project patches directory.

If you want to roll back a patch you applied locally, the easiest way is to follow the steps above to remove or disable the patch. You can then remove the package from it vendor directory and run composer install to return to a clean slate.


Source link