theodorejb/polycast
theodorejb/polycast brings type-safe casting to PHP: a simple Cast class converts values to int, float, bool, string, array, or DateTime, throwing clear exceptions when a value can't be cast instead of silently coercing it.
Architecture fit. Polycast is a stateless, static utility library — a set of explicit conversion helpers (toInt, toFloat, toString, plus nullable variants) that accept mixed and throw InvalidArgumentException on unconvertible input rather than silently coercing to 0/"" the way PHP's native casts do. It has no service provider, no config, no facade, and no framework coupling, so it slots into Laravel without touching the container or boot lifecycle. The natural fit is at boundaries: form request normalization, config/env parsing, queue payload hydration, CSV/import parsing, and DTO construction — anywhere a malformed value should surface as an error instead of a silent zero. It is explicitly not a replacement for Eloquent $casts or the Castable interface; it operates on already-extracted scalars, upstream of model hydration.
Integration feasibility. High. Single Composer require, zero transitive dependencies, MIT license, no published assets. A developer can evaluate it in under an hour. The only integration work is policy: deciding where strictness applies and how InvalidArgumentException maps to the HTTP layer (it must be caught and converted to ValidationException/422, or it becomes a 500).
Technical risk. Runtime risk is low — the surface area is tiny and deterministic. The real risks are:
"1e3"), hex strings, float-to-int rounding, and locale-sensitive float parsing (setlocale with comma decimal separators) is the most likely source of production surprises.composer.json constraint can become the blocking dependency during a PHP 8.x upgrade cycle.Key questions for the maintainer/review.
composer.json."5 ", "05", "1e3", "5.0" into toInt, INF/NAN, and true/false into toString.. as the decimal separator?toString accept Stringable objects / backed enums, or only scalars?master branch?Stack fit. Compatible with Laravel 8–11 on PHP 7.4–8.3 assuming a conventional constraint; verify before committing. Because it is framework-agnostic, it works identically in HTTP requests, queue workers, console commands, and seeders — which is the main argument for it over hand-rolled casts.
Migration path. Do not do a repo-wide replacement of (int)/intval(). Adopt incrementally at the points where silent coercion is a known defect class:
App\Support\Cast) that delegates to Polycast. This is the single most important step — it makes the dependency swappable and confines the import to one file.FormRequest::prepareForValidation() or a custom validation rule, where a thrown exception naturally becomes a 422.Compatibility. No conflict surface beyond the PHP version constraint — there are no shared namespaces or overlapping dependencies. Run composer why-not php and a composer update --dry-run in CI to confirm. If the constraint is too narrow for the target PHP version, fork-and-relax is a viable, low-cost option.
Sequencing. (1) Spike branch with the wrapper helper and 10–15 unit tests over the edge cases above; (2) pin the exact version in composer.json — not a caret range — given the low release cadence; (3) roll out to one vertical slice; (4) instrument: log the exception class and message and alert on volume, since a spike indicates a boundary that needs a validation rule instead; (5) expand only after the slice is clean for a release cycle.
Maintenance. Near-zero ongoing cost: no transitive dependencies means no CVE churn, no security patch treadmill, no version-conflict firefighting. The flip side is no vendor relationship and no SLA. Treat it as a vendored utility in the risk register, not a strategic dependency.
Support. Community-only, effectively best-effort from one person. On-call engineers will not find Stack Overflow answers for this package. Mitigate by keeping the wrapper helper documented in the repo — the team's own abstraction becomes the support surface.
Scaling. Irrelevant as a scaling concern. Static, CPU-only, allocation-light, no I/O, no caching, no state. Cost is negligible at any request volume; it will never be the bottleneck.
Failure modes.
InvalidArgumentException reaching the HTTP layer → 500s on user input that previously "worked" (returned garbage). This is the highest-probability incident and the reason for the wrapper + explicit mapping to validation errors.Ramp-up. Under an hour for any PHP developer; the API is three or four static methods. The real onboarding cost is agreeing on policy — which boundaries are strict and how exceptions are surfaced — and that is a decision the team owns regardless of the library.
TPM recommendation. Adopt as a thin, wrapped utility behind an internal helper, pinned to an exact version, with a pre-approved fallback to fork or reimplement. Do not make it load-bearing in the domain layer. It solves a real and recurring defect class (silent coercion) at a total cost of ownership that is, given the vendoring escape hatch, acceptably low despite the weak popularity signals.
How can I help you explore Laravel packages today?