Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Composer Patches Laravel Package

vaimo/composer-patches

Composer plugin that applies patches to installed dependencies during install and update. Define patches in composer.json using local or remote files, keeping vendor modifications reproducible across every environment and team member.

Deep Wiki
Context7

Getting Started

  1. Install the plugin. Add vaimo/composer-patches to the project. If patches are needed in production builds, install it as a normal dependency, not require-dev:

    composer require vaimo/composer-patches
    

    On Composer 2.2+, explicitly allow the plugin:

    {
      "config": {
        "allow-plugins": {
          "vaimo/composer-patches": true
        }
      }
    }
    
  2. Declare your first patch in the root composer.json under extra.patches, keyed by package name. A minimal entry points at a local patch file:

    {
      "extra": {
        "patches": {
          "vendor/package": [
            {
              "url": "patches/vendor-package/fix-null-check.patch",
              "description": "Guard against null config value",
              "version": "^2.4"
            }
          ]
        }
      }
    }
    

    The schema accepts a URL or local path plus optional metadata such as a version constraint, patch level, description, and hash. The package README is the authoritative reference for the exact fields supported by your version.

  3. Apply and verify. Run composer install (or composer patches:apply if the package is already installed), then inspect status with the plugin’s list command. The plugin registers commands under the patches: namespace (list, apply, undo, reapply); run composer list to confirm the exact set in your installed version.

  4. First real use case: a third-party package has a bug blocking your release. Check out the package source at the installed version, make the smallest possible fix, generate a git diff from the package root, commit it under patches/, register it with a version constraint, and run composer patches:reapply. This keeps the fix reviewable in your repo and automatically reapplied on clean installs.

Implementation Patterns

Keep patches in the repository, not in chat or tickets. Commit patch files alongside the composer.json change. Use a predictable layout such as patches/<vendor>-<package>/<issue-or-slug>.patch. Relative paths resolve predictably and make the patch visible in code review.

Generate patches from the correct root. The most common source of failures is the wrong path prefix. Generate the diff from the package root so the paths match what the applier expects, then set the patch level accordingly. For typical a/file.php / b/file.php diffs, level 1 is correct; if you generate from a parent directory or include the package name in the path, adjust the level or regenerate from the right place.

Use version constraints as guardrails. Attach a version constraint to every patch. When a dependency is upgraded outside the range, the patch is skipped instead of being forced onto incompatible code. This turns a hard install failure into a visible “patch no longer applies” signal. Combine with a hash (sha1 or equivalent) for remote patches so the exact content is pinned.

Sequence deliberately. Patches apply in declaration order. Split unrelated changes into separate files, put foundational patches first, and avoid one giant catch-all diff. Smaller patches are easier to reapply after upgrades and easier to delete individually once upstream fixes land. If your version supports explicit sequencing metadata, use it rather than relying on implicit array order across multiple config files.

Prefer project-level patches for third-party code; package-level patches for internal packages. The plugin also reads patch definitions shipped inside dependency composer.json files. That is useful for private or first-party packages that need to carry their own fixes, but it means consumers can inherit patches implicitly. Audit package-level patches like any other install-time behavior, and avoid using them to silently modify unrelated dependencies.

Configure appliers for non-standard cases. Some patches need git apply --3way, binary handling, or a different working directory. The plugin supports custom applier configuration at the project level and per patch. Define a named applier once, reference it from patches that need it, and keep the default applier for ordinary unified diffs. This is also the escape hatch for unusual patch formats or platforms where patch behaves differently from git apply.

Integrate with CI and deployment. A clean, reproducible pipeline should run composer install with plugins allowed and then assert that patches applied. Add a step that runs the plugin’s list/status command and fails the build if a required patch is pending or failed. Treat patch application as part of dependency installation, not as a manual post-deploy step.

Document removal criteria. For each patch, record the upstream issue or PR and the version in which the fix is expected. When upgrading, remove the patch and its extra.patches entry in the same change. Leaving stale patches with loose version constraints is how projects end up silently running unpatched code.

Gotchas and Tips

  • require-dev plus --no-dev means no patches in production. If the plugin is dev-only, composer install --no-dev will not install it, and none of your patches will be applied. Install it as a regular dependency if production builds depend on patches.
  • Composer 2.2+ blocks plugins by default. Without allow-plugins, the plugin is silently not loaded and patches appear to be ignored. Check composer diagnose and the install output.
  • --no-plugins skips patching entirely. Likewise, environments that disable plugins for security reasons need a different strategy.
  • Already-installed packages do not automatically receive newly added patches on a no-op composer install. Use composer patches:reapply or reinstall the affected package. This is the first thing to check when “the patch is in composer.json but not in vendor.”
  • Root extra is not part of composer.lock. Switching branches with different patch definitions changes behavior without a lock-file diff. Be explicit in code review and CI about which branch’s patches are expected.
  • Failures can be quiet unless you look. Run with -vvv when a patch does not apply, and use the plugin’s list/status command to distinguish “not applied,” “skipped by version constraint,” and “failed to apply.” A version constraint that no longer matches can silently skip a patch you still need.
  • Path prefixes and line endings are the usual culprits. Diffs generated from the wrong directory, CRLF/LF mismatches, file mode changes, and binary files all cause failures. Prefer git apply for binary or mode-sensitive patches and regenerate diffs rather than hand-editing them.
  • Remote patches are a supply-chain surface. Pin to an immutable commit or tag, use HTTPS, and include a hash. Avoid URLs pointing at mutable branches. Treat a remote patch with the same scrutiny as a dependency.
  • Patching Composer plugins or early-loaded packages can be order-sensitive. If the patched package is itself a Composer plugin, its patched code may not be loaded during the same Composer run that applies the patch. Verify in a separate command run.
  • Package-level patches can surprise consumers. A dependency that ships its own extra.patches will modify its own code (or others) when your plugin is active. Review dependency composer.json files during upgrades and keep an inventory of implicit patches.
  • Windows and minimal container images may lack patch. Standardize on git apply via a custom applier, or ensure the patch binary is present in CI and runtime images.
  • Do not hand-edit vendor/ without a patch file. Any manual fix will disappear on the next install. Capture it as a patch immediately, with a test or reproduction note, so the next developer understands why it exists.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin