php-soap/encoding
A PHP library for SOAP encoding and decoding, converting PHP values to and from SOAP XML. It provides the encoding layer for SOAP clients and servers, with support for envelopes, headers, faults, and typed values through a clean, framework-agnostic API.
Architecture fit
php-soap/encoding is a low-level serialization component, not a SOAP client. It handles XML/SOAP envelope construction, XSD type mapping, and encode/decode of message bodies. It has no Laravel service provider, facade, config, or transport layer, so it slots in beneath application code rather than beside it.php-soap/client, php-soap/engine, or a wrapper such as code-distortion/laravel-soap) rather than a direct application dependency. Adopting it directly means we own the transport, WSDL resolution, and error-handling layers ourselves.Integration feasibility
nil semantics, and namespace handling.ProvidesObjectEncoderLens / ProvidesObjectDecoderLens is not portable across this upgrade and must be migrated (array lookup → ElementLookup object, plus explicit miss handling).Technical risk
@ITernovtsii, @NickSdot) diagnosed real correctness bugs, upstream merged them with attribution, and the release is backed by a published benchmark methodology and byte-identical-output verification. Community validation is thin but genuinely engaged, not a single-maintainer monologue. The anomalous 2026-10-16 date noted previously should still be reconciled against Packagist, but release activity is now clearly real.@veewee). MIT license keeps a vendor fork viable, but forking a serializer is an ongoing tax, not a one-time cost.ext-soap in how ref-declared attributes are namespaced (xml:lang, tns:code). If we run a mixed estate — ext-soap for simple endpoints, this package for complex ones — the same logical payload can serialize differently across the two paths. That is a correctness and auditability concern, not just a cosmetic one.xsi:nil. This is semantically better but is a behavioral change on the wire. Vendors with strict or hand-rolled XSD validation, or partners who historically relied on receiving an explicit nil, may reject or misinterpret payloads that were previously accepted. This must be validated against every counterparty, not just against local fixtures.veewee/reflecta ^1.2, veewee/xml ^4.14, php-soap/wsdl-reader ~0.34, and widens dev/runtime allowances for symfony/var-dumper ^8.0 and guzzlehttp/guzzle ^8.0. Verify all of these against our PHP version, locked dependency set, and base images before bumping.Key questions
ProvidesObjectEncoderLens / ProvidesObjectDecoderLens? If yes, this upgrade is a code change plus a test change, not a version bump.DocumentToLookupArrayReader anywhere (including tests, examples, or forked code)? It is removed with no deprecation shim.xsi:nil for absent optional fields? Enumerate endpoints where a missing element is acceptable before rollout.null.EncodingException and fail the whole encode/decode.ext-soap / php-soap/encoding estate? If so, how do we reconcile the new ref-attribute namespacing divergence?import/include), and does 0.36.0 change any of them?Stack fit
ext-soap's SoapClient or a maintained wrapper is cheaper.xsd:anyType / SOAP-ENC Map and Struct decoding materially improves handling of loosely-typed vendor payloads — and strengthens the case against direct adoption for simple endpoints, where ext-soap parity is now less guaranteed than before.Migration path
ext-soap wholesale. Run a strangler pattern: keep SoapClient for stable, simple integrations and introduce this package only where ext-soap demonstrably fails (custom type mapping, non-standard envelopes, strict schema validation, testability). Note that this pattern now carries a parity obligation: the two paths no longer serialize identically for ref attributes, so any endpoint that crosses the boundary needs explicit contract tests.php-soap/client, this package is largely transparent and the migration is a version bump, not a rewrite — but the bump is not behavior-neutral (see compatibility below).SoapEncoderInterface so a future swap to ext-soap, laminas/laminas-soap, or a fork is a container binding change rather than a refactor. This abstraction also absorbs the 0.36.0 ElementLookup churn from the rest of the app.Compatibility
DocumentToLookupArrayReader removed; custom decoder lenses receive Soap\Encoding\Xml\Node\ElementLookup instead of an array; attributes now resolve by exact namespace (mismatched namespace → null, no fallback to same-named child property); throwing custom lenses now raise EncodingException instead of reading as null; absent optional nillable properties are omitted on encode rather than sent as xsi:nil; ref-declared attributes are written in their own namespace.Feature\NullValueAware + NullValueHandling for explicit null semantics per property, and ElementLookup::fromElement() / element() / attribute() as the replacement read path.reflecta ^1.2, veewee/xml ^4.14, wsdl-reader ~0.34) do not collide with anything already locked in the application.ext-soap's own class names — coexistence is normal but must be verified.composer.json, lock them, and configure Renovate/Dependabot for review-only PRs on this dependency. Given 0.36.0's breaking changes inside a 0.x bump, auto-merge must be explicitly disabled.Sequencing
xsi:nil on the wire and uses custom lenses.DocumentToLookupArrayReader, ProvidesObjectEncoderLens, ProvidesObjectDecoderLens, and any lens that throws for control flow. Produce a per-file change list against the 0.36.0 changelog.ElementLookup and measure the real cost.ref-attribute namespacing changes output, confirm acceptance with the vendor in a non-production environment.EncodingExceptions map to a diagnosable error, not a generic 500.ext-soap/a fork based on measured effort.Maintenance
Support
ElementLookup migration means lens-level knowledge is now version-specific; document it alongside the runbook.EncodingException on lens throws gives better diagnostics but can also convert a previously-degraded decode into a hard failure — alerting must distinguish the two.Scaling
stdClass property — means payloads with many sparse/absent fields benefit most. Dense payloads improve least (~43–51%). Sizing estimates should be segmented by payload shape, not averaged.Failure modes
xsi:nil — counterparties with strict or hand-rolled validation may reject or misread the payload.null silently; previously they could fall back to a same-named child property. A field that used to populate now quietly goes empty, which is far harder to detect than an error.EncodingException; a previously tolerated "not found" becomes an outage.ref-declared attributes serialize into their own namespace, diverging from ext-soap — mixed-stack estates can produce inconsistent payloads for the same logical request.DocumentToLookupArrayReader will fatal at autoload/compile time on any lingering reference; this fails loudly and is easy to catch pre-deploy.nil vs empty element.Ramp-up
ElementLookup change is a concrete argument for this: teams behind the abstraction absorb a version bump, teams with lenses scattered through the app absorb a refactor.null deliberately vs leave a property unset), attribute-namespace expectations, and the decision record for choosing this package over ext-soap. Without it, the next maintainer will re-litigate the choice — and will likely get the nil semantics wrong on the first attempt.How can I help you explore Laravel packages today?