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

Pretty Xml Laravel Package

simonschaufi/pretty-xml

A tiny PHP library for pretty printing and minifying XML with configurable indent size and character, since DomDocument can't configure indent distance. Install via Composer: simonschaufi/pretty-xml.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

simonschaufi/pretty-xml is a single-purpose string transformer: a PrettyXml\Formatter object with format(), minify(), and two setters for indent size and character. It sits in the presentation/debug layer, not the domain layer, so it does not touch business logic, persistence, or contracts — the lowest-blast-radius category of dependency.

  • Legitimate gap: DOMDocument normalizes and re-indents output but exposes no indent-width control. This package exists solely to close that gap. If we have any XML-emitting surface (SOAP clients, legacy partner integrations, sitemaps, RSS/Atom feeds, export endpoints), we have this gap today, usually papered over with preg_replace or "good enough" saveXML() output.
  • Scope discipline: the library does not parse, validate, transform, or model XML. That is a feature, not a limitation — it keeps the dependency out of the schema/validation path and makes it trivially replaceable.
  • Wrapping is mandatory, not optional: the public API is an instance with mutable configuration (setIndentSize, setIndentCharacter). Binding it as a Laravel singleton and mutating it per call site invites configuration bleed — catastrophically so under Octane or any long-lived worker, where one request's setIndentSize(2) becomes the next request's default. Wrap it behind a small XmlFormatter interface resolving a fresh Formatter per invocation, or an immutable config-bound factory.
  • Do not copy API names from existing internal notes: the package exposes format(), not prettyPrint(). Any design doc referencing a static PrettyXml::prettyPrint() facade describes a wrapper we would have to build, not the package. Worth correcting before it propagates into code.

Integration feasibility

Straightforward. One composer require, no framework coupling, no service provider, no config file, no facade. The realistic engineering cost is measured in hours, not days, and most of it is wrapper plus tests, not adoption.

  • Composer-only install; PHP 7.4 floor per the 2.0.0 release notes (verify against our runtime baseline).
  • Dependencies are PHP core only — no transitive supply-chain surface to audit.
  • MIT license; forking and vendoring are both legally unencumbered.
  • Testable by construction: input string in, output string out. Adding format(format($x)) === format($x) as a regression assertion is cheap and locks in the 3.1.1 behavior.

Technical risk

The technical risk is low; the organizational risk is that we over-invest in a 22-star utility and treat it as infrastructure.

  • Correctness model: this is a token/regex-style reformatter ported from vkBeautify, not an XML parser. The README's own precondition is input that is "well-formed and valid." It will not catch malformed XML and should never be positioned as a validator. Feed it only what DOMDocument/SimpleXMLElement has already accepted.
  • Whitespace semantics: pretty-printing rewrites text nodes. Any payload with mixed content (<p>Hello <b>world</b></p>), or where downstream systems are whitespace-sensitive, is at risk. Release 3.1.1 ("reach a fixpoint when formatting text nodes") tells us successive formatting passes previously drifted — that is precisely the defect profile that bites stacked middleware, cache-then-reformat paths, and queued re-processing.
  • Version floor: pin ^3.1.1. Taking ^3.0 reintroduces non-convergent formatting, and 3.0.0 was itself a full algorithm rewrite — two consecutive majors touching the core algorithm is a signal that output stability is still maturing.
  • Bus factor: single maintainer, 0 dependents, 22 stars. We would likely be the largest consumer. That is acceptable only because the blast radius is a formatter and the code is small enough to fork.
  • Data anomaly: the supplied metadata lists a last release of 2026-09-25. Treat release metadata as unverified and confirm the actual tagged version on Packagist before pinning.

Key questions

  1. Which endpoints actually emit XML, and how many of them are ours to change? (Owner: backend leads.)
  2. Does any payload pass through formatting more than once — global middleware plus route middleware, cache-then-reformat, queued post-processing? If yes, ^3.1.1 is a hard floor.
  3. Are any of those payloads whitespace-sensitive or mixed-content (SOAP envelopes, partner schemas with text-node significance)? (Owner: integration owners; blocks rollout, not pilot.)
  4. Do we need pretty-printing in production at all, or is minification sufficient and pretty-printing a debug-only concern?
  5. What is our largest realistic payload? Anything over ~1 MB needs a benchmark before middleware rollout.
  6. Build vs. buy: with a surface this small, is a 40-line internal formatter plus wrapper cheaper than an external dependency we must track? (Recommendation: adopt, but wrap — the wrapper is the hedge and costs the same either way.)

Integration Approach

Stack fit

Native PHP/Laravel. No stack change, no runtime capability required, no infrastructure implication. It complements rather than competes with existing tooling: Response::xml() for emission, SimpleXMLElement/DOMDocument for parsing and validation, PHPUnit/Laravel XMLAssertions for verification. The package occupies only the "string → prettier string" slot.

Migration path

  1. Wrap first, call second. Build App\Support\XmlFormatter (interface plus a PrettyXmlFormatter implementation that instantiates a fresh Formatter per call and applies indent config from config/xml.php). This is the entire migration insurance policy.
  2. Inventory, then pilot. Grep for saveXML, asXML, preg_replace on XML, and response()->xml. Pilot on one non-critical, well-formed, non-whitespace-sensitive endpoint; diff before/after output byte-for-byte.
  3. Standardize in middleware only after pilot passes, and only for application/xml/text/xml content types, with an explicit re-entry guard (response header or attribute). 3.1.1 makes re-entry safe, but the guard keeps intent legible to the next engineer.
  4. Environment-gate the behavior: minify in production, pretty-print in local/staging unless a caller opts in. This eliminates the performance and whitespace risk from the production path entirely.
  5. Lock behavior with tests: assertXmlStringEqualsXmlString() for equivalence, plus format(format($x)) === format($x) for idempotency. Run the same fixture set against representative partner payloads.

Compatibility

  • Framework-agnostic; verify against our supported Laravel/PHP matrix rather than assuming. No service provider means no version-coupling risk to Laravel internals.
  • Works on raw strings, DOMDocument::saveXML(), and SimpleXMLElement::asXML() output — those last two are the natural call sites.
  • Documented limitations to accept up front: doctype/namespace handling and comment/processing-instruction preservation are not guaranteed by the formatter (minify($xml, true) is the opt-in for comments). Any schema depending on exact original indentation is out of scope.
  • Backward compatible by construction — adoption is per-call-site and opt-in.

Sequencing

Step Priority Effort Gate / Dependency
Verify package metadata and Pin ^3.1.1 High Low Packagist check
Build XmlFormatter wrapper + fresh-instance-per-call High Low None
Inventory XML-emitting surfaces High Low None
Idempotency + equivalence regression tests High Low Wrapper
Pilot on one non-critical endpoint Medium Low Inventory
Middleware rollout, env-gated Medium Medium Pilot diff clean
Whitespace-sensitive payload review High Medium Integration owners
Performance benchmark >1 MB Medium Low Pilot
Team enablement + wiki Low Low Rollout

Note the ordering: the whitespace review gates rollout, not the pilot or the wrapper. Do not serialize everything behind it.


Operational Impact

Maintenance

  • Cost is near zero and mostly passive. One dependency, one version constraint, occasional composer update. Budget realistically at a few hours per quarter, dominated by "is it still maintained?" checks rather than code changes.
  • Fork contingency: MIT plus a small surface means the fallback is not a migration project — it is vendoring the formatter class. Keep the wrapper interface stable and the fork option stays a one-day task.
  • Pin discipline: constrain to ^3.1.1 in composer.json, not just the lockfile, so lockfile regeneration cannot silently walk back the idempotency fix.
  • Upgrade posture: expect algorithm-level churn given 3.0.0 was a rewrite and 3.1.x is still fixing convergence. Read changelogs on minor bumps; treat the formatter as behaviorally significant, not cosmetic.

Support

  • Internal, self-serve. No vendor, no SLA, no upstream support channel beyond GitHub issues on a low-traffic repo. Do not route production incidents to the maintainer.
  • Onboarding artifact: one wiki page — when to use format() vs minify(), the fresh-instance rule, the environment gating, and the explicit warning that this does not validate XML.
  • Discoverability: a pretty-xml tag plus a note in the XML/integration runbook so the next person debugging "why did our XML output change" finds the cause in minutes rather than hours.

Scaling

  • Minification is effectively free; pretty-printing is CPU-bound string work that scales with payload size and nesting depth. Under high request volume on large payloads, it is measurable — benchmark rather than assume a number.
  • Mitigations are conventional and cheap: restrict pretty-printing to non-production, cache minified output for repeated identical responses, or move large-document formatting off the request path entirely.
  • Memory profile follows the input string; no accumulator or tree is retained. No database or infrastructure implications.
  • Octane/horizon caveat: mutable formatter state in a long-lived worker is the one scaling-adjacent defect this package can cause. The fresh-instance-per-call wrapper resolves it; do not skip it.

Failure modes

Scenario Impact Mitigation
Mutable Formatter bound as singleton, config set per call site Cross-request config bleed (severe under Octane); output inconsistency Fresh instance per call; never mutate a shared instance
Formatting applied at multiple layers Output drift / non-convergence on pre-3.1.1 Pin ^3.1.1; still gate re-entry explicitly
Whitespace-sensitive or mixed-content payload reformatted Downstream contract breach, silent Restrict to known-safe endpoints; prefer minify(); review with integration owners
Malformed XML passed to formatter Garbled output, no error raised Validate upstream with DOMDocument before formatting
Performance regression on large payloads Latency spike on XML endpoints Benchmark >1 MB; env-gate pretty-print; cache minified output
Package abandoned or PHP-incompatible release Stalled upgrades Wrapper interface + MIT fork/vendor option
Doc examples drift from real API (prettyPrint doesn't exist) Wasted engineering hours, broken snippets Wrapper owns the vocabulary; correct internal docs before rollout
Unverified release metadata (future-dated release) Wrong pin decision Confirm on Packagist before shipping the constraint

Ramp-up

  • Backend engineers (~30 min): format() vs minify(), the wrapper's fresh-instance rule, environment gating, and the explicit "not a validator" boundary.
  • QA (~30 min): assertXmlStringEqualsXmlString() equivalence checks plus the double-format idempotency assertion, and a fixture set drawn from real partner payloads — not synthetic ones, since the failure mode is whitespace in production data.
  • Adoption metrics: count endpoints and middleware behind the wrapper, confirm every environment reports >= 3.1.1, and re-survey after two weeks. If after a sprint the number of call sites is one or two, that is a legitimate outcome — the correct conclusion is "this solved a small problem cheaply," not "we should have built a platform around it."
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.
mydnic/volet-feature-board
wmde/fundraising-phpcs
friendlylabs/surveyr
mg-techlegend/laravel-notify-africa
islamabdurahman/laravel-sms-service
dmhendricks/b2-sdk-php
aplicativa/laravel-admin
ezavalishin/vkma
jackardios/laravel-json-api-paginate
viral/laravel-adminpanel
dieppk/log-viewer
daimakuai-ext/helpers
codexshaper/php-blade-view
abraxas81/charts
adamlien/laravel-cas
quimgc/tasks
sistem-atc/bank-sdk
core45/laravel-cookieconsent
projectsend/community-modules
ovac/laravel-hubtel-payment