tsantos/serializer
A PHP serialization library for Laravel projects that converts objects to arrays and JSON using configurable metadata, with support for custom handlers, relationships, and versioned API output.
Architecture fit. tsantos/serializer is a framework-agnostic, code-generation-based serializer: metadata is read at build time and compiled into plain PHP classes that are invoked at runtime, avoiding per-request reflection. Architecturally this makes it a performance-optimized adapter at the boundary of a Laravel app — the layer that converts Eloquent models/DTOs into arrays or JSON for HTTP responses, queue payloads, and webhook fan-out. It is not a Laravel package: it ships no service provider, facade, config stub, or model integration. In a Laravel codebase it therefore occupies the same slot as symfony/serializer, spatie/laravel-data, or hand-rolled JsonResource transformers, and must be wrapped behind an application-owned interface (e.g. App\Contracts\Serializer) to remain replaceable. Fit with Laravel's idioms is neutral-to-poor: Eloquent's lazy-loading proxies, collections, Carbon, and enum casting all need explicit normalizers/handlers that this package does not provide out of the box.
Integration feasibility. Technically feasible but entirely bespoke: a TPM should budget a custom ServiceProvider (builder/factory binding, metadata driver config, cache-path config, config/serializer.php) plus a warmup artisan command. The generated-code cache directory is the crux — it must be writable at build time, baked into the deploy artifact, and readable at runtime. That is a clean fit for a build-step pipeline and a poor fit for read-only container filesystems, and it introduces an explicit deploy-ordering dependency (ship generated classes with the code, never generate on first request in production). Estimated spike: 3–5 engineer-days to prove parity on two representative endpoints.
Technical risk — high. This is the dominant finding. The last release is December 2018, the project has 28 stars and zero dependents, meaning no community validation, no downstream bug reports, and no incentive for anyone but us to fix issues. Concrete exposures:
readonly, enums, and first-class callable syntax are almost certainly unsupported in metadata parsing and in generated code; union/intersection types and never returns are unhandled.doctrine/annotations for the annotation driver, which is deprecated and removed in doctrine/annotations 2.x; modern Laravel (10/11/12, PHP 8.1+) will likely produce Composer conflicts or require --ignore-platform-reqs hacks that we should refuse to ship.Key questions.
Carbon/DateTimeImmutable, backed enums, circular references, polymorphic relations, API versioning/groups?symfony/serializer (with compiled metadata caching) or spatie/laravel-data close 80% of the performance gap at 5% of the risk?Stack fit. Best-case fit is a Laravel 8/9 application on PHP 7.4 where the package's own test matrix is closest to reality. For Laravel 10+ / PHP 8.2+, treat adoption as a fork-and-modernize project, not an install. The package's genuine strength — compiled, reflection-free serialization — is stack-independent, which is precisely why forking is viable if the performance need is real.
Migration path. Do not replace existing transformers directly. Introduce an application-owned Serializer contract, implement it first with the incumbent (JsonResource / symfony/serializer), then add a TsantosSerializerAdapter. Because the compiled output is deterministic, run shadow mode in staging: serialize the same models through old and new paths, diff the JSON byte-for-byte, and fail the build on any delta. Only flip traffic after a clean parity window on real fixtures.
Compatibility. Validate up front with a composer why-not / composer update --dry-run pass against every supported Laravel major; pin the PHP constraint explicitly and add config.platform.php so CI and prod agree. Confirm extensions and doctrine/annotations version bounds. Prefer the PHP-array or YAML metadata driver over annotations to sidestep the doctrine/annotations 2.x removal entirely — that single decision removes the largest near-term compatibility landmine. Verify the generated cache path against .gitignore/.dockerignore and include it in the build artifact.
Sequencing.
symfony/serializer with compiled metadata and against handwritten transformers, on our two heaviest endpoints, with our real payloads. Gate: ≥30% serialization-time reduction to justify continuing.Note the opportunity score (0.59) against an overall score of 0.17: the underlying idea — compiled serialization for hot paths — has real merit; the specific artifact does not, unmodified.
Maintenance. Post-adoption, we own the code. Expect a fork with an active CI matrix across two or three PHP versions, a PHP 8 compatibility branch, and periodic dependency bumps. Realistically 1–2 engineer-days per quarter of steady-state ownership, spiking to 10–15 days for the initial modernization — plus the ongoing cost of every new PHP minor being a potential generated-code incompatibility. This is the single largest TPM-level objection: we are acquiring a small legacy codebase, not a dependency.
Support. There is none. No maintainer response, no issue triage, no release cadence, no security advisory pipeline, and no vendor to escalate to. Internal escalation must route to the named fork owner; if that person leaves, the bus factor is one. Mitigate with documentation, a written upgrade runbook, and — critically — the swap-out adapter so abandoning the fork later is a config change.
Scaling. Where it shines: compiled serializers give predictable, low-variance CPU per request, minimal allocation, and no reflection cache stampede at cold start, which is genuinely valuable at high RPS on large object graphs. Where it bites: generated classes are one file per serialized type, so a large domain or a multi-tenant schema multiplies disk footprint and opcache memory; warmup adds build time proportional to the class count; and a monolith with hundreds of DTOs may see opcache pressure that erodes the latency win. Horizontal scaling is fine provided the generated artifact is baked into the image — do not share a writable cache volume across pods.
Failure modes.
DateTime, enums, or decimals to strings/null without error.composer update breaks the build because the package's constraints are frozen at 2018.Ramp-up. Moderate. Developers must learn the metadata format (annotations or YAML), understand that the runtime classes are generated and not editable, and internalize the "regenerate before deploy" habit. Budget a half-day onboarding doc plus a lint/CI check, and expect the first two incidents to be cache-related. Restrict authorship of serializer metadata to one or two engineers initially to keep the generated surface coherent.
TPM recommendation. Do not adopt as a runtime dependency on a modern Laravel stack. Either (a) reject in favor of symfony/serializer with compiled metadata or spatie/laravel-data, or (b) pursue the fork path only if the one-week benchmark gate demonstrates a material, measured win on a genuinely hot path, with a named owner and a funded 15-day modernization. In both cases, land the adapter interface first so the decision stays reversible.
How can I help you explore Laravel packages today?