Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Types Laravel Package

tdn/php-types

A small PHP utility for working with types: safely cast values, validate data against expected types, and normalize scalars, arrays and objects. Lightweight and framework-agnostic, it drops easily into Laravel or any Composer project.

View on GitHub
Deep Wiki
Context7

Getting Started

tdn/php-types is a plain PHP library that boxes scalar and array values in small wrapper objects (StringType, IntType, FloatType, BooleanType, ArrayType-style classes — see the naming caveat below). There is no Laravel service provider, no facade, and no config file, so integration is a single Composer dependency plus whatever wiring you build yourself.

Minimal steps:

  1. composer require tdn/php-types:^2.0 — pin the minor explicitly. The most recent tag is 2.0.1, which is still a 2015-era release (the package is archived; there is no PHP 8 modernization in this line). If Packagist resolution fails on your PHP version, add the GitHub repo as a VCS repository and pin the 2.0.1 commit.
  2. Open src/ first, not the README. Two things changed in 2.0.1 that make this mandatory rather than merely advisable: the release adds class aliases so that names colliding with PHP 7 reserved keywords (String, Int, Float, Boolean, Array) keep working, and it adds an invoke method to Boolean. Do not trust a class name you remembered from 1.x or from a blog post — read which file holds the real implementation and which is the class_alias() shim.
  3. Run the package's own tests against your target PHP version (8.1+) before writing any application code. 2.0.1 ships "updated tests", but "updated" here means updated in 2015. Treat a green suite on your actual PHP minor as the gate for adoption.
  4. First use case: wrap untyped request input at the boundary of a controller or form request. Instead of trusting $request->input('age') to be an integer, construct an IntType from it once and pass the wrapper inward, unwrapping to a scalar only at the Eloquent save and the JSON response.

That boundary-wrap-then-unwrap discipline is the only pattern that consistently pays for itself with a library this small.

Implementation Patterns

Normalize at the edge, unwrap at the edges. The wrapper's value is that it fails or coerces once, in one place, rather than in five scattered (int) casts. Pattern: controller → form request validates shape → construct typed wrappers from the validated input → services and domain methods accept wrappers → repository/Eloquent boundary calls ->getValue() (or (string)/(int) casts where supported) to persist primitives.

DTOs and value objects. If you already hand-roll DTOs for API payloads, wrappers give you cheap invariant enforcement without pulling in a full value-object framework. A Money or Age DTO whose constructor takes IntType documents its contract better than a @param int docblock. Keep it shallow though — one level of wrapping, not wrappers inside wrappers.

Boolean flags via invoke() (new in 2.0.1). BooleanType now exposes an invoke method, which lets you treat the wrapper as a callable — useful inside @if ($flag()) in Blade or when($flag(), ...) in a pipeline without an explicit ->getValue() at every site. Adopt it deliberately: it reads well in views and poorly in domain code, where an explicit unwrap documents the boundary. Pick one convention per layer and stick to it; mixing $flag() and $flag->getValue() in the same service is how reviewers start guessing.

Guard clauses in actions and jobs. Because the wrapped value is validated at construction, queued jobs and service methods can assume the type holds and skip defensive re-checks. This is most useful in jobs where the serialized payload has crossed a process boundary and you re-hydrate from array data.

API resources. Add an explicit unwrap step in your JsonResource::toArray() rather than relying on the wrapper to serialize. Returning the object directly usually yields {} in JSON (see Gotchas). A one-line $this->age->getValue() per field is clearer than debugging a JsonSerializable implementation.

Laravel casts and accessors. Do not point an Eloquent $casts entry at a wrapper class. Eloquent's cast contract expects to hydrate from and dehydrate to scalars and will not know how to reconstruct the wrapper. Use a custom accessor that returns the wrapper and a mutator that unwraps it, or keep wrappers out of models entirely and confine them to the service layer.

Wrap behind your own interface. Define a narrow Age, Email, or Slug interface in your app and have the tdn class implement it via a thin adapter. This is the single highest-leverage move: when you eventually migrate to native typed properties, backed enums, or a maintained package, you swap adapters instead of grepping for IntType across the codebase. Given the package is archived, plan the exit before you plan the entry. The 2.0.1 aliases reinforce this — you do not want your app's ::class strings resolving to a class_alias() shim whose other name may disappear in whatever 2.1 never ships.

Gotchas and Tips

  • Archived and unmaintained since 2015. No security fixes, no PHP 8 compatibility work. Expect deprecation notices at minimum and hard failures (dynamic properties, removed functions, old-style array/string offset syntax) at worst. Pin the version and run CI on your actual PHP minor. 2.0.1 does not change this verdict — it is a 2015 patch, not a revival.
  • Aliased class names (2.0.1). Classes whose names collide with PHP 7 reserved keywords were given aliases. That means two names may resolve to the same type, instanceof checks and ::class strings depend on which name you imported, and container bindings or config arrays keyed by class string can mismatch silently. Pick one canonical name, use it everywhere, and note it in your adapter so nobody "fixes" it later.
  • Coercion semantics are the whole ballgame. Verify what new IntType('abc') does — throw, return 0, or return null. If it silently coerces, the library gives you a false sense of type safety and you are better off with a Laravel validation rule.
  • JSON serialization. Wrapper objects do not serialize to scalars. Either implement JsonSerializable in an adapter subclass or, more simply, unwrap in your resources. Never let a wrapper reach response()->json() unwrapped.
  • Comparison. Wrappers compare by object identity. $a == $b and $a === $b will both behave unintuitively for equal values. Look for an equals()/isSame() method and standardize on it; otherwise unwrap both sides before comparing.
  • Performance. Object allocation per scalar adds up in tight collection loops and large result-set mapping. Unwrap before ->map() over thousands of rows.
  • Serialization into queues and sessions. serialize()/unserialize() across a deploy that changes the class shape can break job payloads — and 2.0.1 did touch class shape via aliases, so payloads written by an older deploy are exactly the scenario the docs warn about. Prefer primitives in queue payloads and re-wrap on handle.
  • Debugging. dd($wrapper) shows object internals rather than the value; dump($wrapper->getValue()) is your reflex. When a value looks wrong, the bug is almost always at construction, not at read. With invoke() in play, also remember that dump($flag) and dump($flag()) print different things — the first shows the object, the second the boolean.
  • No service provider, no config. Any global behavior (strict vs. coercing mode, default locale for numeric formatting) is your responsibility — put it in a small factory or binding in AppServiceProvider so you are not scattering new IntType(...) with inconsistent flags. This is also the right place to centralize the canonical-vs-alias naming decision.
  • Zero dependents. There is no community usage to lean on for answers. Budget time to read the source yourself; it is small enough that this is feasible, which is also the main argument for using it as a learning/reference implementation rather than production infrastructure. The 2.0.1 release notes are three bullets long and the linked data is empty — the source is your only reliable specification.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource