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

Vendor Patches Laravel Package

symplify/vendor-patches

Symplify Vendor Patches generates vendor patches for your Composer packages with a single command. Copy a vendor file with a .old suffix, edit the original, then run generate to create patch files and auto-configure cweagans/composer-patches.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. symplify/vendor-patches sits entirely outside the application runtime. It is a dev-time generator: you edit a file in vendor/, preserve the pristine copy as <file>.old, run vendor/bin/vendor-patches generate, and it emits a unified diff into patches/ plus the extra.patches block in composer.json. The actual re-application at install time is performed by cweagans/composer-patches, not by this package. That distinction matters for evaluation: this is a thin, single-purpose code generator, and the operational risk profile is dominated by the Composer plugin it feeds, not by the generator itself. There is no Laravel coupling whatsoever — no service provider, no config file, no container binding — so it fits any Composer-based PHP stack equally.

Integration feasibility. High for the narrow case, medium for the general case. Installing is a two-line Composer command measured in minutes. The harder work is process: deciding when patching is permitted, who owns the patch register, how patches are reviewed, and how they are retired. A team can be productive on day one with a single patch, but a sustainable practice requires a written policy and a CI check. Budget roughly one engineering day for adoption (pilot patch, plugin allow-list, CI verification, runbook) and treat the ongoing cost as an interest payment on technical debt.

Technical risk.

Risk Severity Notes
Patch silently not applied in production High Occurs if cweagans/composer-patches is installed with --dev while deploys run composer install --no-dev. The app boots, the bug is "fixed" in staging, and production is unpatched. This is the single most dangerous failure mode because it has no error signal.
Patch drift after dependency upgrade Medium Hunk #N FAILED breaks the build loudly, which is safe but disruptive. Each bump of a patched package is a manual reconciliation.
Workflow state lives only in a gitignored vendor/ Medium There is no ledger of "which files are currently hand-edited." The .old suffix convention is the only marker, and generate will happily patch anything that differs.
Silent key mismatch for private/path repos Medium Without --resolve-from-directory, the extra.patches key won't match an installed package; patch generates, applies to nothing.
Composer plugin blocked by allow-plugins Low Deterministic and immediately visible once you know the cause.
Generator abandonment / supply chain Low MIT, small surface, and the output artifact is a plain diff — exit cost is minutes.
cweagans v1→v2 format break Low–Medium Existing --- /dev/null patches must be rewritten to --- <file-path>; migration errors look like path-stripping bugs.

Key questions for the adopting team.

  1. Does every deploy target run a real composer install with dev-dependencies excluded, or does anything ship a pre-built vendor/ artifact?
  2. Is cweagans/composer-patches an accepted allow-plugins entry in our Composer policy, and is that policy enforced centrally?
  3. What is the maximum number of live patches we will tolerate, and what is the maximum age of a patch without an upstream PR link?
  4. Who owns patches/ in code review, and is a .patch file treated as reviewable source?
  5. Do we consume any private VCS or path repositories where the installed directory name diverges from composer.json name?
  6. Which packages are already being hand-edited in vendor/ today, and is that practice documented anywhere?

Integration Approach

Stack fit. Compatible with Composer 2 and Laravel 10/11/12; the current release targets PHP 8.4, so teams on 8.1–8.3 should pin a compatible version rather than float. It works cleanly with Forge and Envoyer, which run composer install as part of the deploy. Laravel Vapor builds during the deployment pipeline and will also apply patches, but only if the plugin is a production dependency. The one environment to avoid is anything that caches and reuses a vendor/ directory between builds — a stale cache will serve unpatched or wrongly patched code with no error.

Migration path. Do not roll this out as a general capability. Roll it out as a controlled remedy for one specific, currently-blocking upstream defect. The sequence is: reproduce the bug in staging → confirm no configuration-level workaround exists → patch one file → generate → verify on a clean install → ship → open the upstream PR the same day. Then, and only then, write the policy that governs patch #2 onward.

Compatibility notes worth encoding in a runbook.

  • cweagans/composer-patches must be a non-dev dependency if any environment runs --no-dev.
  • With the v2 plugin, generate is followed by composer patches-relock and composer patches-repatch.
  • composer.json is mutated by generate, so composer update --lock is mandatory; skipping it trips lock-hash validation.
  • Generated patches use paths relative to the package root and are applied with -p1. Do not hand-edit prefixes.
  • macOS runners may hang on patch application; install gpatch and prioritise it on PATH.
  • Prefer --patches-file=patches.json if the team wants the mapping as a separate, reviewable artifact rather than buried in extra. Prefer --patches-output if patches/ is already used by a JS toolchain.

Sequencing.

  1. Pilot (half day). One patch, one engineer. Prove the full loop end to end, including a destructive rm -rf vendor && composer install and a deploy to staging.
  2. Guardrails (half day). Add the allow-plugins entry, confirm the deploy pipeline's Composer invocation, add a CI step that fails on composer.lock hash drift, and add a CI step that re-runs composer install --verbose from clean.
  3. Policy (half day). Written rules: patch requires an upstream issue link; patch requires an owner; patch count capped; every patch reviewed as source.
  4. Register (ongoing). A small table in the repo — package, file, reason, upstream PR, date opened, review date — that turns an implicit practice into a managed backlog item.
  5. Retirement drill. Deliberately upgrade a patched package, hit the expected failure, and exercise the re-patch procedure once, on purpose, before you have to do it under incident pressure.

Operational Impact

Maintenance. The generator itself is essentially zero-maintenance; a dev-dependency bump once or twice a year. The real maintenance load is patch drift. Estimate 30–60 minutes per patched package per upgrade cycle to reinstall clean, re-apply the edit against the new version, re-copy .old, re-generate, re-lock, and re-verify. At five live patches across a fast-moving dependency set, that is a recurring drag on every upgrade sprint. Cap the register and give every patch an expiry review date.

Support. Small ecosystem: ~192 stars, no dependents, a single-maintainer project (Symplify/Tomas Votruba), maturity described only by its README. The narrow scope substantially offsets the bus-factor concern — the tool emits text diffs and nothing else, and the critical path is cweagans/composer-patches, which is far more widely deployed. Escalation for a generator defect realistically means "hand-write the diff"; that escape hatch should be documented rather than discovered during an incident.

Scaling. Patch count scales linearly in effort but superlinearly in cognitive load, because each patch adds a compatibility constraint to every future dependency bump. Practical ceiling for a product team is a handful — three to five — and anything beyond that is a signal to fork the package, vendor it, or block the upgrade instead. Multi-team scaling introduces a second pressure: patches/ and extra.patches in the root composer.json become a merge-conflict hotspot, so assign one owning team for the directory and require a rebase-before-push convention.

Failure modes, ranked by what a TPM needs to watch.

  • Silent non-application (highest concern): no error, wrong code in production. Mitigate with a deploy-time assertion — a smoke test that exercises the patched behaviour, or a build step that greps the installed vendor file for the patched line.
  • Hard hunk failure: build breaks loudly on upgrade. Annoying but safe; it is the failure mode you want.
  • Lock hash drift: blocks installs on strict CI. Trivial fix, easy to forget in a busy PR.
  • Unintended patch capture: generate sweeps everything that differs from its .old counterpart, so a teammate's leftover debugging edits become committed patch content. Enforce a clean-tree rule before regenerating.
  • Wrong package key: patch generates and applies to nothing, with no diagnostic.

Ramp-up. A competent Laravel engineer unfamiliar with the tool needs one to two hours to be productive and a half day to be safe, mostly spent understanding the --no-dev trap and the cweagans v2 relock/repatch sequence. Team-level ramp-up is a short README in the repo plus the patch register. Net TPM verdict: adopt narrowly, budget for drift, and measure success by the rate at which patches are removed rather than added — a healthy register trends toward empty.

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.
dakiquang/laravel-oauth-refresh-lock
woda/laravel-worktrees
dalefranks/ramasite
faghy/laracashbook
roundly-consulting/google-places-for-laravel
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
adachsoft/changelog-linter