Download the PHP package treptow-labs/envelope without Composer
On this page you can find all versions of the php package treptow-labs/envelope. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download treptow-labs/envelope
More information about treptow-labs/envelope
Files in treptow-labs/envelope
Package envelope
Short Description A PHP data transfer object library with support similar to the Rust Option type.
License
Informations about the package envelope
Envelope
Envelope is a small PHP library for building DTOs that know the difference between "this field was not provided" and "this field was explicitly set to null."
It's built around a Option / Some / None type (similar to Rust's Option<T> or Java's Optional<T>), and an Envelope base class that turns "not provided" properties into fields that are automatically omitted from your DTO's array/JSON output.
The problem
null is overloaded. Say you have a PATCH /users/{id} endpoint backed by a DTO like this:
If a client sends {"name": "Jane"}, how do you know they didn't mean to touch bio — versus a client sending {"name": "Jane", "bio": null}, who is explicitly asking you to clear bio?
Once a field is nullable, you can no longer use null as a sentinel for "not provided," because null is also a legitimate value. The usual workarounds — checking array_key_exists everywhere, sprinkling isset() checks through your update logic, or maintaining a parallel list of "dirty" fields — get messy fast, especially once a DTO has more than a couple of optional fields.
Envelope solves this by giving every property two possible states instead of two:
Some($value)— the field was provided, and here's the value (which itself might benull)None— the field was not provided at all
Your DTO stays a normal, typed PHP class, but toArray() / toJson() will only ever include the fields that were actually provided — making it safe to feed straight into Model::update(), Model::fill(), or any other partial-update code path.
Installation
Option, Some, and None
Option is an abstract class with two concrete implementations:
Somewraps a present value (which may itself benull)Nonerepresents the absence of a value
You can also build an Option from a raw value, optionally providing a sentinel that counts as "none":
Building a DTO with Envelope
Extend Envelope and type each property as an Option. Calling toArray() (or toJson()) will unwrap every Some and skip every None automatically:
Notice that isActive is present with a value of null (the "explicitly cleared" case) while bio doesn't appear at all, because it was never provided.
Populating a DTO from request data: EnvelopeResolver
EnvelopeResolver wraps a raw array (e.g. $request->validated()) and gives you typed accessors that return Some if the key was present in the array, None if it wasn't:
Available accessors, all following the same pattern:
| Method | Returns |
|---|---|
get(string $key, ?Closure $callback = null) |
Raw value, optionally transformed by $callback |
string(string $key, bool $nullable = true, bool $throw = false) |
Cast to string |
int(string $key, ...) / integer(...) |
Cast to int |
float(string $key, ...) |
Cast to float |
boolean(string $key, ...) |
Cast via FILTER_VALIDATE_BOOLEAN |
array(string $key, ...) |
Cast to array |
enum(string $key, string $enumClass, bool $nullable = true) |
An instance of $enumClass, via $enumClass::tryFrom() |
Each of these:
- Returns
Noneif the key isn't present in the data at all. - Returns
Some(null)if the key is present but its value isnulland$nullableistrue(the default). - Returns
Some($castValue)if the key is present with a non-null value. - If the key is present, the value is
null, and$nullableisfalse: either returns a type-appropriate empty value ('',0,0.0,false,[]) or throwsUnresolvableValueException, depending on$throw.
Every accessor has an ...OrThrow sibling (stringOrThrow, intOrThrow/integerOrThrow, floatOrThrow, booleanOrThrow, arrayOrThrow) that's shorthand for calling it with nullable: false, throw: true; useful for fields that were provided but must not resolve to null:
Shaping the output: attributes
Three attributes let you control how a property is serialized without touching your update logic.
#[MapsTo] - rename the output key
#[Omit] - always exclude a property from toArray output
Useful for properties you need on the DTO for internal logic but never want serialized, regardless of whether they're Some or None:
#[FormatUsing] - transform the value before it's output
Pass a Formatter class (and any constructor arguments it needs):
Envelope ships with two formatters out of the box:
DateTimeFormatter- formats aDateTimeInterfacevalue to a string (defaults toDateTimeInterface::ATOM); non-DateTimeInterfacevalues pass through unchanged.StringFormatter- safely casts a value tostring, passingnullthrough asnulland calling__toString()onStringableobjects.
You can write your own by implementing the Formatter interface: