mtownsend/collection-xml
mtownsend/collection-xml adds a simple toXml() macro to Laravel collections and arrays, making it easy to convert nested data into clean XML for feeds, APIs, exports, and legacy integrations.
Architecture fit. The package is a Laravel Collection macro — it extends a first-party abstraction rather than imposing a layer, contract, or directory structure. It slots in as a utility, not an architecture decision. Fit is high for bounded, one-directional work: turning an array into XML for a legacy SOAP/RSS/sitemap consumer, or turning an XML response into a collection for map/filter/pluck chaining. Fit is poor as a general-purpose XML layer — there is no schema validation, no streaming, and no attribute/namespace strategy that survives round-tripping.
Integration feasibility. Trivial. composer require, package auto-discovery registers the service provider, the macro is globally available. No config publishing, no migrations, no worker changes, no external service. Prototype effort is measured in hours, not days. This is the cheapest kind of dependency to trial.
Technical risk.
simplexml_load_string invocation uses safe libxml flags and behaves predictably on DOCTYPE.Key questions.
Stack fit. Laravel-native (service provider + macro), PHP 8 compatible, no coupling beyond illuminate/support. Compatible with Laravel 10/11/12 in principle — verify the composer constraint against our lockfile before committing rather than assuming.
Migration path. Additive; nothing to migrate. If we currently hand-roll SimpleXMLElement construction or string-concatenate XML, this replaces that and is a readability win. The rule is that it must not leak into the domain layer.
Recommended shape. Do not let ->toXml() / Collection::fromXml() be called ad hoc across the codebase. Introduce a narrow internal boundary:
App\Xml\XmlEncoder and App\Xml\XmlDecoder interfaces, with a CollectionXmlDriver implementation.XMLWriter (streaming) or symfony/serializer is a one-class change.app/Support/ a legitimate fallback if the dependency becomes a maintenance liability. That is a decision point, not a day-one action.Compatibility. Pin an explicit version range. The package is small enough that a minor bump could alter output formatting — XML declaration, whitespace, self-closing tags — which partner systems notice. Add golden-file tests asserting byte-level output for representative payloads so a dependency bump fails CI instead of failing an integration.
Sequencing.
Maintenance. Low ongoing cost: small surface, low change velocity. The real maintenance artifact is the golden-file suite — that is what protects us from upstream drift and from silent behavior changes in PHP's libxml. Budget roughly half a day a year to review upstream; otherwise treat it as frozen.
Support. No SLA, GitHub issues only, single maintainer. The escalation path is "we read the source," which is genuinely viable at this size. Do not place it on a revenue-critical path without accepting the fork-it-ourselves fallback as a real option.
Scaling. CPU cost is negligible. Memory scales with document size because parsing is DOM-based; the practical ceiling is a few MB per document. Above that — feeds, 50k-URL sitemaps, bulk partner files — use XMLWriter/XMLReader. This package is the wrong tier for streaming workloads, and that boundary should be documented rather than discovered.
Failure modes to instrument.
Ramp-up. A mid-level Laravel developer is productive in under an hour; the conceptual load sits in XML semantics, not the package. The onboarding cost worth budgeting is the guardrail itself — write "not for payloads requiring attributes, namespaces, or schema validation" into the interface docblock, because that is precisely where teams get burned.
Verdict. Adopt as a convenience utility behind an internal adapter, scoped to small, one-directional, internally-owned XML payloads. Reject for partner-contract XML with attributes or namespaces, XSD validation requirements, or large documents.
How can I help you explore Laravel packages today?