A class defines properties, methods and constants. PHP’s object model was rebuilt for PHP 5. See the manual’s Classes and Objects chapter. Interfaces and traits have their own page, as do enums.
Declaration
[#[attribute]] {abstract | final | readonly} class Name [extends Parent] [implements Interface {, Interface}]
{
{constant | property | method | use Trait; | case}
}
final class Point
{
public const ORIGIN = [0, 0];
public function __construct(
public readonly int $x = 0,
public readonly int $y = 0,
) {}
public function distanceTo(self $other): float
{
return hypot($this->x - $other->x, $this->y - $other->y);
}
}
$p = new Point(3, 4);
echo $p->distanceTo(new Point()); // 5
- A class name is case-insensitive, and shares a namespace with interfaces, traits and enums. It cannot be a reserved word.
- A class extends at most one parent (
extends), and may implement any number of interfaces. abstractstops a class being instantiated, andfinalstops it being extended.readonly class(PHP 8.2) makes every property readonly. See Readonly classes.$a->baccesses a member of an object. Inside a method$thisis the object, and a member must be reached through$this; there is no implicit member scope.Foo::classand$obj::class(PHP 8.0) give the class name as a string.- A class with no parent or interfaces, declared at the top level of a file, can be used before its declaration. In other cases do not rely on it: put the declaration first or use autoloading.
Properties
{modifier} [type] $name [= constant-expression] ;
{modifier} [type] $name [= default] { hooks }
| Modifier | Effect |
|---|---|
public, protected, private | Visibility. var is the old spelling of public |
static | Belongs to the class, not to an object |
readonly | Can be set only once |
final | Cannot be redeclared in a child (PHP 8.4) |
public private(set) | Asymmetric visibility (PHP 8.4) |
- A property without a visibility modifier is public, as with
var,staticorreadonlyalone. - A default must be a constant
expression.
newis not allowed in a property default. - A typed property (PHP 7.4)
with no default is uninitialised. Reading it throws
Error. An untyped property with no default isnull. - A property type cannot be
void,neverorcallable. Types are invariant when overriding. - Reading an undefined property gives a warning (a notice before 8.0) and
null.
Dynamic properties
Assigning to an undeclared property creates it on that object only. Since
PHP 8.2 this is
deprecated, except on stdClass and in classes marked
#[\AllowDynamicProperties]. A class can also take control of undeclared
names with __get() and __set().
Readonly properties
A readonly property
(PHP 8.1) may be
initialised once, from inside the class, and never changed after that.
- It must have a type (use
mixedfor any value). It cannot have a default, because that would mean it was already set. PHP 8.6 adds defaults for readonly properties; see Versions. - It cannot be
static, and readonly static properties do not exist. - It is initialised by assignment from the scope where it is declared. Since PHP
8.4, a readonly property is implicitly
protected(set), so a child class may set it; before that the initialising scope had to be the declaring class. - Once set, reassigning it, compound assignment,
++,unset(), taking a reference and writing through array syntax all throwError. - Only the property is frozen. An object held in it can still change.
- Since PHP 8.3, it can be reinitialised in
__clone(). Since 8.5,clone()can set it on the copy.
Readonly classes
readonly class
(PHP 8.2) applies
readonly to every instance property, including promoted ones. It can have
only typed properties and no static properties, and dynamic properties are not
allowed. A readonly class may only be extended by another readonly class. Anonymous
readonly classes are allowed since PHP 8.3.
Property hooks
Property hooks (PHP 8.4) attach
code to reading and writing a non-static property. A hooked property ends in a block
instead of a semicolon, and has at least one of get and
set.
class Person
{
public string $name {
set => ucfirst(strtolower($value)); // short set: the result is stored
}
public string $first {
get => explode(' ', $this->name)[0]; // virtual: no storage of its own
}
public int $age = 0 {
get { return $this->age; }
set(int|string $value) { // wider than the property type
$this->age = (int) $value;
}
}
}
- A
sethook receives the new value as$value, or under a name given in its parameter. Its parameter type must be the property’s type or a wider one. get => expr;andset => expr;are short forms. The shortsetstores the expression’s result.- A property whose hooks refer to itself as
$this->nameis backed and has storage. A property with no such reference is virtual. A virtual property with only agethook cannot be written. - Hooks are incompatible with
readonly, and exist only on non-static properties. - Indirect writes bypass
set, so taking a reference and writing array elements are restricted. A hook named&getreturns by reference. - A child may override individual hooks and reach the parent’s with
parent::$prop::get()andparent::$prop::set($v). A hook, or the property, may befinal. __PROPERTY__gives the name of the property inside a hook.
Asymmetric visibility
A property can have different visibility for reading and writing
(PHP 8.4), written
public protected(set). It needs a type. Static properties gained it in
PHP 8.5.
- The set visibility must be equal to or narrower than the get visibility:
protected public(set)is an error. publicmay be left out:private(set) string $xmeanspublic private(set) string $x.private(set)impliesfinal.- Taking a reference, and writing to an array in the property, need set visibility.
- No spaces are allowed inside:
private( set )is an error.
Class constants
class Http
{
public const OK = 200;
protected const NOT_FOUND = 404;
final public const string NAME = 'http'; // typed, PHP 8.3
}
echo Http::OK;
- A constant is defined once per class, is public by default, and is read with
Class::NAME,self::NAMEorstatic::NAME. - The value is a constant expression, which may refer to other constants.
finalconstants (PHP 8.1) cannot be redefined by a child. Interface constants can be overridden since 8.1.- Typed constants (PHP 8.3) are declared after the modifiers.
Foo::{$name}fetches a constant by name at run time (PHP 8.3).constant()does the same for a string.
Methods
{abstract | final | static | visibility} function [&] name ( parameters ) [: type] { statements }
- A method is called with
$obj->m(), or on the class withFoo::m()if static. Method names are case-insensitive. - An overriding method must be compatible with the parent:
covariant return type, contravariant parameter types, same or wider visibility, and no
new required parameter.
__construct()is exempt. A failure is a compile error. - An
abstractmethod has no body and afinalmethod cannot be overridden. Private methods cannot be final, except__construct(). #[\Override](PHP 8.3) makes a method declare that it overrides, so that a typo or removed parent method is a compile error.- A static method has no
$this. Calling one through an object is allowed. Calling an instance method statically throwsErrorsince PHP 8.0.
Visibility
| Keyword | Accessible from |
|---|---|
public | Anywhere |
protected | The class, its parents and its children |
private | Only the declaring class |
Access is checked against the class of the code, not the object. A private property redeclared in a child is a separate property. Visibility can be widened in a child but not narrowed. Methods with no modifier are public. Class constants have had visibility since PHP 7.1.
Constructors and destructors
__construct() runs on each new object. A parent’s constructor runs only
if the child calls parent::__construct(), or defines no constructor of its
own. Before PHP 8.0 a method named after its class could act as a constructor. In 8.0
it became an ordinary method.
Constructor promotion
A constructor parameter with a visibility modifier or readonly
(PHP 8.0) is also a
property, assigned automatically from the argument. Since 8.5 final works
too.
class Money
{
public function __construct(
public readonly int $amount,
protected string $currency = 'GBP',
) {}
}
A promoted parameter cannot be callable, and may not be declared as a
property as well. Attributes on it apply to both the property and the parameter.
A default is given to the parameter only, so the property has no default.
New in initialisers
Since PHP 8.1, new may be used in parameter defaults, static variable
initialisers, global constants and attribute arguments. The class name must be
static and arguments must be constant expressions. It is not allowed in class
constants or property defaults.
Destructors
__destruct() runs when the last reference to an object goes away, or at
script shutdown in an unspecified order. It also runs after exit(). A
parent destructor is not called automatically. Throwing from a destructor during
shutdown is a fatal error.
Static members
A static property or method belongs to the class. Inside the class, use
self:: for the current class, parent:: for the parent and
static:: for the class actually called. $obj::$prop and
$className::method() work with a value on the left.
Late static binding
static:: (PHP 5.3) refers to the class named in the most recent
non-forwarding call. A call of the form Foo::method() or
$obj->method() is non-forwarding: it sets the called class.
self::, parent:: and static:: are forwarding:
they keep the called class that was already set.
class Model {
public static function create(): static { return new static(); }
public static function name(): string { return static::class; }
}
class User extends Model {}
echo get_class(User::create()); // User
echo User::name(); // User
self:: would resolve to Model hereMagic methods
Methods whose names start with two underscores are reserved. These are called by the
engine (manual).
All must be public except __construct(), __destruct() and
__clone(). If declared types are used, they must match the documented
signature.
| Method | Runs when |
|---|---|
__construct(...) | A new object is created |
__destruct(): void | The object is destroyed |
__get(string $name): mixed | Reading an inaccessible or undeclared property |
__set(string $name, mixed $value): void | Writing one |
__isset(string $name): bool | isset() or empty() on one |
__unset(string $name): void | unset() on one |
__call(string $name, array $args): mixed | Calling an inaccessible method on an object |
static __callStatic(string $name, array $args): mixed | Calling one statically |
__toString(): string | The object is used as a string. Such a class implements Stringable automatically (PHP 8.0) |
__invoke(...) | The object is called as a function |
__clone(): void | After the object is copied by clone |
__debugInfo(): array | var_dump() needs the list of values to show |
static __set_state(array $p): object | Restores code produced by var_export() |
__serialize(): array, __unserialize(array $d): void | serialize() and unserialize() (PHP 7.4) |
__sleep(): array, __wakeup(): void | The older serialisation hooks. Soft-deprecated in PHP 8.5 |
Overloading methods are called only for names that cannot be accessed from the current
scope. They cannot take arguments by reference. Inside __get(), using the
same undefined property does not call __get() again.
Cloning
clone $x creates a copy of an object and, if the class has one, runs
__clone() on the copy. The copy is shallow: properties holding objects
still refer to the same objects, so __clone() usually clones those
itself.
class Doc {
public DateTime $date;
public function __clone(): void { $this->date = clone $this->date; }
}
$copy = clone $original;
Since PHP 8.5
clone may also be called as a function with an array of properties to
change on the copy. Those are set after __clone(), respect
visibility, and work on readonly properties:
readonly class Colour {
public function __construct(public int $r, public int $g, public int $b) {}
public function withGreen(int $g): static { return clone($this, ['g' => $g]); }
}
Enum cases cannot be cloned. Comparing objects: == is true if both are
instances of the same class with equal properties, and === only if they
are the same instance.
Anonymous classes
new class (args) extends Base implements I { … }
(PHP 7.0) declares a class in
an expression. Every run of the same declaration creates an object of the same class. Its
name is generated by the engine and should not be used. A surrounding class’s private
members are not automatically accessible inside it. Pass values in through the
constructor.
Lazy objects
Since PHP 8.4 the Reflection API can create objects whose initialisation is deferred
until first use, with ReflectionClass::newLazyGhost() and
ReflectionClass::newLazyProxy(). This is a run-time feature with no syntax
of its own.