Technically\Undefined is a clever way of emulating undefined values in PHP8.
Thanks to enums and union types we can finally have undefined in PHP.
With arrays, you can distinguish between null value and missing key.
However, it is not an option for class properties or typed method parameters.
For typed properties and method parameters you would normally use null as
"no value". But what do you do if null is also a valid value? Then you need
another "nullish" thing to use instead. Like undefined in JavaScript.
The package provides an enum for representing undefined values: Technically\Undefined.
- You can use it to type class properties and method parameters (e.g.
string | Undefined) - You can refer the enum case to define default values to properties and parameters (
Undefined::VALUE) - There are several utility methods in the
Undefinedenum which you can use to make your code more elegant
use Technically\Undefined;
function hello(string | Undefined $name = Undefined::VALUE) {
return $name === Undefined::VALUE ? "Hello!" : "Hello, {$name}!";
} Check if the given value is Undefined.
Check if the given value is not Undefined.
This method is particularly useful for callbacks:
array_filter($array, Undefined::isNotUndefined(...))Check if the given value is nullish β either null or Undefined.
Check if the given value is not nullish β neither null nor Undefined.
This method is particularly useful for callbacks:
array_filter($array, Undefined::isNotNullish(...))Check if the given value is empty.
This method follows the semantics of the standard empty() function,
but also adds support for Undefined values β treating them as empty too.
Check if the given value is not empty.
This method follows the semantics of the standard empty() function,
but also adds support for Undefined values β treating them as empty too.
This method is particularly useful for callbacks:
array_filter($array, Undefined::isNotEmpty(...))Return the first non-empty value.
This method follows the semantics of the standard coalesce operator in PHP: ?: (aka "elvis operator"),
but also adds support for Undefined values β treating them as empty too.
return Undefined::coalesce($delay, self::DEFAULT_DELAY);Return the first non-nullish value.
This method follows the semantics of the standard null coalesce operator in PHP: ??,
but also adds support for Undefined values β treating them as nullish too.
return Undefined::nullishCoalesce($delay, self::DEFAULT_DELAY);use Technically\Undefined;
function hello(string | null | Undefined $name = Undefined::VALUE) {
return match ($name) {
Undefined::VALUE => 'Hello, stranger!',
null => 'Hello!',
default => "Hello, {$name}!",
};
}Note how null is a possible valid value for updating user organization:
use Technically\Undefined;
final readonly class UserUpdateRequest
{
public function __construct(
public string | Undefined $name = Undefined::VALUE,
public string | Undefined $email = Undefined::VALUE,
public Organization | null | Undefined $organization = Undefined::VALUE,
) {
// Nothing
}
}With undefined with can have one big all-in-one "update" method for changing
properties of an immutable object:
use Technically\Undefined;
readonly class Address {
public function __construct(
public string $name,
public string $line1,
public string $line2 = '',
public string $city,
public string | null $state = null,
public string $zip,
public string $country,
) {
// Nothing
}
public function with(
string | Undefined $name = Undefined::VALUE,
string | Undefined $line1 = Undefined::VALUE,
string | Undefined $line2 = Undefined::VALUE,
string | Undefined $city = Undefined::VALUE,
string | null | Undefined $state = Undefined::VALUE,
string | Undefined $zip = Undefined::VALUE,
string | Undefined $country = Undefined::VALUE,
) {
return new self(
name: $name !== Undefined::VALUE ? $name : $this->name,
line1: $line1 !== Undefined::VALUE ? $line1 : $this->line1,
line2: $line2 !== Undefined::VALUE ? $line2 : $this->line2,
city: $city !== Undefined::VALUE ? $city : $this->city,
state: $state !== Undefined::VALUE ? $state : $this->state,
zip: $zip !== Undefined::VALUE ? $zip : $this->zip,
country: $country !== Undefined::VALUE ? $country : $this->country,
);
}
}
$address = new Address(
name: 'Sherlock Holmes',
line1: '221B Baker Street',
city: 'London',
zip: 'NW1 6XE',
country: 'England',
);
$address = $address->with(name: 'Dr. John H. Watson');This project is licensed under the terms of the MIT license.
Authored by πΎ Ivan Voskoboinyk.
