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 Json Manipulator Laravel Package

symplify/composer-json-manipulator

Symplify ComposerJsonManipulator provides a PHP API for reading, modifying, and writing composer.json files safely. Update dependencies, scripts, config, and metadata, then save normalized JSON—ideal for tooling, migrations, and automated package maintenance.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is a build-time, dev-only utility, not an application dependency. It belongs in the tooling layer — CI scripts, monorepo split jobs, package-skeleton generators, or a custom artisan make:package command — and should never appear in the production image or require block. For a standard Laravel application that only ever runs composer require, the package has no architectural role: Composer already owns composer.json mutation, and competing with it is where most of the risk lives. It earns its place only if we have a repeatable, programmatic need to construct or merge manifests from templates (e.g., scaffolding internal packages, generating per-tenant or per-service manifests, or fanning a shared dependency set across a multi-repo fleet).

Integration feasibility. Mechanically trivial — composer require --dev symplify/composer-json-manipulator and a three-object API (ComposerJsonFactory/ComposerJsonFileLoader → ComposerJson → save). The real feasibility question is dependency resolution, not effort: Symplify packages pin Symfony/Nette component ranges that were current at their last release, and Laravel 10/11 pulls symfony/* at a much newer major. Expect conflicts that surface only at install time; validate early with composer why-not symplify/composer-json-manipulator <version> against the actual Laravel skeleton before committing to a spike.

Technical risk. High, and concentrated in provenance. Zero stars and zero dependents on this listing is a strong abandonment signal, and the Symplify ecosystem split and retired a large number of its single-purpose packages; the packagist entry may be explicitly marked abandoned with no suggested replacement. Concretely:

  • No upgrade path. PHP 8.3/8.4 support is unlikely to arrive; a future Laravel upgrade that raises the PHP floor can strand the tool mid-quarter.
  • Semantics drift. Merging composer.json is not generic array merging. require-dev, autoload.psr-4, repositories, extra.laravel.dont-discover, config.platform, and scripts each have distinct, version-sensitive merge rules. A library that models them as nested arrays will be subtly wrong the moment Composer changes behavior.
  • Formatting churn. Round-tripping through a JSON encoder rewrites key order, indentation, and escaping, producing large noisy diffs and merge conflicts on a file every developer touches.
  • Write safety. Non-atomic saves on a file that, if corrupted, breaks the entire build.

Key questions.

  1. What is the actual job-to-be-done — scaffolding new manifests, mutating existing ones in CI, or merging a shared baseline into N repos? The answer changes the recommendation.
  2. Is the packagist entry marked abandoned, and is there a stated replacement?
  3. Does Composer\Json\JsonManipulator (shipped inside composer/composer, already present in every build) cover the need? It does targeted add/remove/set on sections while preserving formatting — it is maintained by the Composer team and is the correct default.
  4. Would composer require --no-update plus a human commit be sufficient? Often it is, and it removes the dependency entirely.
  5. Who owns this tool internally when upstream goes quiet?

Integration Approach

Stack fit. Dev/CI only. Install as require-dev in the tooling repository (or a dedicated tools/ composer project), never in the application. If it must run inside a Laravel command, gate the command behind app()->environment('local') and keep the class out of the production autoload path via composer install --no-dev.

Recommended path — do not adopt as-is. Two better options, in order:

  1. Composer\Json\JsonManipulator from composer/composer, which is already in vendor/ as a transitive artifact of any Composer-driven build and is trivially added as an explicit dev dependency. It handles section-level edits without reformatting the file.
  2. ~150 lines in-house. A thin ComposerManifestEditor contract with two methods (mergeBaseline(array $baseline, string $path), setRequirement(string $package, string $constraint)), implemented over json_decode/json_encode with explicit, unit-tested rules for the six or seven keys we actually touch. This is genuinely small, and we own it.

Migration path if the package is already in use. Wrap it immediately behind that same internal interface so call sites are agnostic, pin the exact version, and vendor the source into the repo if packagist availability is a concern. The interface is the migration seam; the swap to JsonManipulator becomes a one-class change.

Compatibility gating. Run the spike against the oldest and newest PHP in our supported matrix, and against a real Laravel skeleton composer.json rather than a synthetic fixture. Confirm the encoder preserves trailing newlines, 4-space indentation, and unescaped slashes — otherwise every run dirties the working tree and breaks git diff --exit-code checks.

Sequencing.

  1. Week 1 — spike. Reproduce one concrete target workflow with both candidates (symplify vs. JsonManipulator) on the real manifest. Fixture-based tests: merge a baseline with no overlap, with overlapping require, with conflicting constraint on the same package, with overlapping psr-4 prefixes.
  2. Week 2 — decide. Gate on: installs cleanly on PHP 8.1–8.3, byte-identical output when no change is needed, no dropped keys, no formatting churn.
  3. Week 3 — wrap and wire. Land the interface, the CI job, and a composer validate --strict post-step.
  4. Week 4 — document and hand off. Runbook plus owner named.

If step 1 fails any gate, fall through to JsonManipulator and close the ticket — the fallback is not a compromise.

Operational Impact

Maintenance. This is the decisive cost. An abandoned dev dependency is survivable, but only if we budget for it: someone must own the vendored copy, watch for PHP-version breakage on each Laravel upgrade, and be prepared to fork. Compare that against JsonManipulator, whose maintenance is a free rider on Composer's release cadence and is exercised by millions of installs. The in-house option's maintenance load is a 150-line file with our own tests — likely lower total cost than monitoring a dead upstream.

Support. No vendor, no SLA, no issue triage. Internal ownership is mandatory from day one; there is no escalation path.

Scaling. Build-time only, so no runtime scaling surface. Two practical limits: (a) CI wall-clock — file I/O and JSON encoding are negligible, but if the tool runs per-package across a large monorepo, batch the edits into one process rather than N; (b) concurrency — parallel CI jobs writing the same composer.json will interleave. Serialize or fan out to per-job worktrees.

Failure modes to design against.

Failure Impact Mitigation
Non-atomic save interrupted mid-write Corrupt manifest, broken build Write to temp file, rename()
Silent key drop on unknown/extra sections Lost Laravel discovery config Round-trip assertion test on the real skeleton
Formatting rewrite Diff noise, merge conflicts, blocked --exit-code gates Byte-equality test when no semantic change
Merge semantics wrong for psr-4/repositories Broken autoloading, wrong package source Explicit per-key rules, not deep-merge
Read-only filesystem / permissions in CI Job failure at an awkward point Fail fast with a clear message; validate writability up front
Lock file drift after manifest edit Non-reproducible builds Always follow with composer update --lock or a full resolve step, committed together

Ramp-up. The public API is small enough for one engineer to learn in an afternoon; the actual learning curve is Composer's merge semantics, which is the same regardless of library choice and is the part worth writing down. Budget one day for the spike and half a day for the runbook. Do not spread this across the team — one owner, one document, one decision record explaining why we did or didn't take the dependency.

Bottom line. Score 0 with zero dependents and a likely-abandoned upstream makes this a poor bet for anything load-bearing, and the capability is already available from a maintained source. Recommend evaluating Composer\Json\JsonManipulator first and treating this package as a fallback only if it demonstrably handles a merge case JsonManipulator cannot — which, given the section-level granularity of our likely needs, is improbable.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib