zendframework/zend-xml2json
Converts XML to JSON using PHP's DOM and JSON extensions, letting you transform XML documents or strings into JSON output ready for APIs, storage, or JavaScript consumption.
What the package actually is. zendframework/zend-xml2json is a narrow utility from the Zend Framework ecosystem: a small Xml2Json class plus a console binary that converts an XML document into a JSON string (attributes, nested elements, and text nodes mapped by convention). It is not a Laravel package, not a service provider, and not an integration layer — it is a single-purpose converter with one runtime dependency on the Zend XML component (and through it, the Zend DOM/entity-loading surface).
Architecture fit. Poor for a Laravel application as a long-lived dependency. Laravel's XML handling conventions (Symfony Serializer/DomCrawler, SimpleXMLElement, or spatie/array-to-xml for the inverse direction) already cover this need, and those are maintained under active release cadences. Introducing an archived Zend-namespaced package means a second, unmaintained XML abstraction living beside Symfony's — two competing DOM/entity configurations in one process, which is exactly the kind of duplication that creates inconsistent XXE posture across code paths.
Integration feasibility. Mechanically trivial — composer require and a new Xml2Json() call — but the low value density is the point. Composer's abandoned flag will surface a warning on every install and update, which is a governance problem for a TPM owning supply-chain hygiene: it trains teams to ignore abandonment warnings. The package also predates PHP 8 in its release line (last tag 2019-10-16), so its dependency constraints on zendframework/zend-xml 2.x almost certainly conflict with a modern Laravel 10/11 stack running PHP 8.2+. Whether it installs at all depends on Composer resolving to an unmaintained transitive branch.
Technical risk. Four material risks:
composer audit / GitHub Advisory coverage. Any libxml entity-handling hardening added upstream post-2019 is not available to you.Key questions to resolve before any commitment.
laminas/laminas-xml2json acceptable, or is the correct move to delete the dependency and use Symfony's serializer behind a domain DTO?Position. For a TPM, this is a reject-as-new-dependency candidate (score 0.2225 is directionally correct). The only defensible use is a short-lived, isolated bridge in a legacy migration — never in a new greenfield service, and never on a path that touches untrusted XML.
Stack fit. Effectively none. There is no Laravel service provider, no config surface, no facade, no publishable assets, and no queue/event awareness. Wiring it in means writing an application-level adapter — at which point you are building the integration yourself, and the package contributes only the mapping heuristic. The dependency footprint it drags in (zendframework/zend-xml) is itself archived and superseded by laminas/laminas-xml.
Recommended target architecture. Do not adopt the package. Instead:
XMLReader for streaming or Symfony DomCrawler/Serializer for bounded documents, with libxml_disable_entity_loader semantics handled explicitly (LIBXML_NONET, no LIBXML_NOENT) or, on PHP 8+, entity loading disabled by default — but state this in code, not in assumption.json_encode(..., JSON_THROW_ON_ERROR) so malformed UTF-8 and depth violations surface as exceptions rather than false.If the legacy shape must be preserved byte-for-byte. Use laminas/laminas-xml2json — the maintained continuation of the same codebase, same API, same mapping conventions — pinned to a version with a PHP 8.x constraint, and wrapped in a single adapter class behind an interface. That gives you a one-file swap when you retire it. Verify the constraint resolution in a throwaway branch before committing to the plan; do not assume the fork's PHP support matches your runtime.
Migration path. Sequenced in four steps:
composer.lock for zendframework/* and confirm whether other Zend packages are already present (a common legacy signature). Bundle the remediation if so.XmlToJsonConverter as a domain port with the current implementation as the first adapter, so step 4 is a container binding change, not a refactor.composer audit, and add a CI check that fails on abandoned packages to prevent the next one.Compatibility notes. Expect friction at the Composer level rather than the code level: PHP 8.2+ runtime against a 2019-era constraint set, plus potential overlap with symfony/serializer's bundled XML handling. Validate on a branch with the full test suite and a production-shaped XML corpus, not with composer require --dry-run alone.
Maintenance. The dominant cost. An archived package has no upgrade path, no CVE response, and no compatibility guarantees with future PHP or libxml releases. It is a permanent, silent liability on the dependency register, and the effort to remove it only grows with time as more code accretes around its output shape. The "maintenance saving" of reusing an existing converter is illusory — you pay it back at the removal, with interest.
Support. No maintainer, no issue tracker in scope, no vendor. Internal support is the only support, which means an on-call engineer debugging a JSON mapping anomaly with no upstream to escalate to. Budget for that in the ownership model: name a team, not a person.
Scaling. The converter is whole-document, not streaming. Memory scales with document size times queue concurrency, so throughput is bounded by the largest payload, not by CPU. For batch ingestion (nightly partner feeds, S3 drop-and-process), this forces either a hard payload size cap, a dedicated low-concurrency queue, or a rewrite to streaming. Model this explicitly with a worker memory limit and a documented maximum accepted document size — otherwise the first oversized file becomes a production incident.
Failure modes to instrument.
false from json_encode and a downstream empty payload. Mitigate with JSON_THROW_ON_ERROR and alerting on converter exceptions, not just on HTTP 5xx.composer update failing or, worse, resolving a stale transitive branch. Mitigate by pinning and by the abandoned-package CI gate.Ramp-up. Near zero — the API is one class and one method, so a mid-level engineer is productive in an hour. That low ramp-up is precisely what makes the package attractive in a deadline and what makes it dangerous: the cost is entirely deferred, and the people who made the adoption decision will have moved on before it lands. For a TPM, that asymmetry — cheap now, expensive later, invisible in the middle — is the argument for spending the extra week on a typed DTO boundary today.
How can I help you explore Laravel packages today?