PHP Type System Evolution
PHP has evolved from a loosely typed language to a strongly typed one. PHP 8.x adds union types, enums, named arguments, and intersection types — making code dramatically safer and more self-documenting.
Union Types
<?php
// Union type: accepts int OR string
function processId(int|string $id): string {
return "ID: " . $id;
}
echo processId(42); // ID: 42
echo processId('abc42'); // ID: abc42
// Nullable shorthand: ?Type = null|Type
function findUser(?int $id): ?array {
if ($id === null) return null;
return ['id' => $id, 'name' => 'Rahul'];
}
// Return union types
function divide(int $a, int $b): int|float|false {
if ($b === 0) return false;
$result = $a / $b;
return is_int($result) ? $result : $result;
}
Enums (PHP 8.1+)
<?php
// Pure enum
enum Status {
case Active;
case Inactive;
case Pending;
}
// Backed enum (with scalar value)
enum Color: string {
case Red = 'red';
case Green = 'green';
case Blue = 'blue';
public function label(): string {
return match($this) {
Color::Red => 'Danger',
Color::Green => 'Success',
Color::Blue => 'Info',
};
}
}
$c = Color::Red;
echo $c->value; // 'red'
echo $c->name; // 'Red'
echo $c->label(); // 'Danger'
// From scalar value
$blue = Color::from('blue'); // Color::Blue
$maybe = Color::tryFrom('purple'); // null (no error)
// Use in type hints
function applyStatus(Status $s): void {
echo $s->name;
}
applyStatus(Status::Active); // Active
Named Arguments
<?php
// Positional (traditional)
array_slice($array, 0, 5, true);
// Named — skip optional params, any order
array_slice(array: $array, offset: 0, length: 5, preserve_keys: true);
// Skip middle optional params
function createUser(
string $name,
string $email,
string $role = 'member',
bool $verified = false,
bool $active = true
): array {
return compact('name','email','role','verified','active');
}
// Only pass what you need
$user = createUser(
name: 'Rahul',
email: 'r@example.com',
verified: true // skip role, active stays default
);
Intersection Types (PHP 8.1)
<?php
interface Countable { public function count(): int; }
interface Stringable { public function __toString(): string; }
// Intersection: must implement BOTH interfaces
function process(Countable&Stringable $obj): void {
echo $obj->count() . ': ' . $obj;
}
Q: What is the difference between a backed enum and a pure enum?
A pure enum has no associated scalar value — cases are just names. A backed enum assigns each case a string or int value, enabling from() and tryFrom() for converting scalars to enum cases, and value property access. Use backed enums when you need to store the enum in a database or pass it over APIs.
Comments (0)
No comments yet. Be the first!
Leave a Comment