PHP Typed Properties: How They Work
This article explores the implementation and behavior of typed properties introduced in PHP 7.4 and refined in subsequent versions. You will learn how to declare type hints for class properties, understand how PHP handles the uninitialized state, and discover how this feature improves type safety and code readability in modern PHP development.
Declaring Typed Properties
Starting in PHP 7.4, you can declare types for class properties. This ensures that any value assigned to a property strictly matches its defined type, preventing type-related bugs.
Here is a basic example of typed properties in a class:
class User {
public int $id;
public string $name;
public ?string $email; // Nullable string
}In this example, $id must always be an integer,
$name must be a string, and $email can either
be a string or null.
Supported Types
PHP supports a wide range of types for class properties, including:
- Scalar types:
bool,int,float,string - Compound types:
array,object - Special types:
iterable,mixed(PHP 8.0+) - Class and Interface names: Restricts the property to an instance of a specific class or interface.
- Union types (PHP 8.0+): Allows multiple types, such
as
private int|float $number;. - Intersection types (PHP 8.1+): Requires the value
to satisfy multiple interface constraints, such as
private Iterator&Countable $collection;.
Note: The types void and callable are
not supported as property types.
The Uninitialized State
When a typed property is declared without a default value, it starts
in an uninitialized state. This is different from
having a value of null.
class Product {
public string $sku;
}
$product = new Product();
// Accessing $product->sku here will throw a Typed Property ErrorIf you attempt to read a typed property before it has been
initialized (either via a default value or inside the constructor), PHP
throws an Error exception:
Fatal error: Uncaught Error: Typed property Product::$sku must not be accessed before initialization
To check if a property has been initialized without triggering an
error, you can use the isset() function:
if (isset($product->sku)) {
echo $product->sku;
}Type Coercion and Strict Types
By default, PHP will attempt to coerce values to the declared property type if strict types are not enabled.
class Profile {
public int $age;
}
$profile = new Profile();
$profile->age = "30"; // Coerced to integer 30However, if you declare declare(strict_types=1); at the
top of your file, PHP will throw a TypeError if you attempt
to assign a value that does not match the exact type definition.
Readonly Properties (PHP 8.1 and Later)
PHP 8.1 introduced the readonly modifier for typed
properties. A readonly property can only be initialized once, usually in
the constructor, and cannot be modified afterward.
class Book {
public readonly string $isbn;
public function __construct(string $isbn) {
$this->isbn = $isbn;
}
}Any attempt to modify $isbn after its initial assignment
will result in a Fatal error.