skip to content

Object-Oriented PHP

How PHP builds objects: typed, readonly and hooked properties, single inheritance plus interfaces and traits, late static binding and enums. Interviewers probe what the 8.x releases changed.

part ofPHPoverview, primer and where to startread it →
on this pageshow

explore

questions

page 2 of 2

In PHP 8.3 and later, what do typed class constants add, and when does static::NAME instead of self::NAME matter?

level: middleimportance: should knowfreq 38%

basics

~20 s

Since PHP 8.3 a class constant can declare a type, and a subclass override must keep a compatible type. self::NAME reads the constant of the class the code is in; static::NAME reads the called class's value, so a subclass override takes effect.

open as a page

In PHP, when a subclass does not redeclare a parent's static property, do the parent and subclass share one value, and why does that matter?

level: middleimportance: should knowfreq 30%

basics

~20 s

Yes. An inherited static property that the subclass does not redeclare is the same storage as the parent's, so writes through Child::$x change Parent::$x too. Redeclare it in the subclass, or key an array by static::class, to get per-class values.

open as a page

In PHP, what rules govern a trait's abstract methods, static members, properties and constants once the trait is used by several classes?

level: middleimportance: should knowfreq 32%

basics

~20 s

Abstract trait methods are requirements the host must implement compatibly. Static state exists once per using class, not per trait. A host may redeclare a trait property or constant only identically, and trait constants (8.2) and static members are used through the using class.

open as a page

In PHP, how do insteadof and as resolve two traits that define the same method, and what else can the as operator change?

level: middleimportance: should knowfreq 42%

basics

~20 s

Two traits defining the same concrete method make PHP fail until insteadof picks one. The as operator adds an alias so the excluded body stays callable, and can also change visibility or, since 8.3, make the method final.

open as a page

In PHP, when exactly does __destruct run, and why is it risky to rely on a destructor to flush or commit work?

level: seniorimportance: should knowfreq 40%

basics

~20 s

__destruct runs as soon as the last handle to an object disappears, or at shutdown if the object is still alive. Fatal errors skip it, cycles delay it and shutdown order is undefined, so commit work explicitly.

open as a page

A PHP app stores order statuses as a string-backed enum in the database; what breaks when you rename a case, change a value or add a case?

level: seniorimportance: should knowfreq 32%

basics

~20 s

The stored ->value is the contract. Renaming a case breaks code and anything that stored the name; changing a value makes from() throw ValueError on old rows; adding a case makes every default-less match throw UnhandledMatchError until handled.

open as a page

In PHP 8.5, how does clone() with its $withProperties argument work, and why does it suit wither methods on readonly classes?

level: seniorimportance: should knowfreq 25%

basics

~10 s

Since PHP 8.5, clone($obj, ['prop' => $value]) shallow-copies the object, runs __clone(), then assigns the listed properties on the copy, even readonly ones, respecting visibility and set hooks. Withers become one line.

open as a page

In PHP 8.4 and later, when would you declare a property on an interface instead of a getter method, and what can implementing classes satisfy it with?

level: seniorimportance: should knowfreq 18%

basics

~20 s

Since PHP 8.4 an interface can require a public readable, writable or read-write property with { get; }, { set; } or both. Implementers may use a plain public property, a hooked or virtual property, or, for get-only, a readonly one.

open as a page

A PHP settings class exposes config keys as properties through __get; what does that hide from IDEs and static analysers, and how would you redesign it?

level: seniorimportance: should knowfreq 36%

basics

~20 s

Magic __get hides every property name and type from tools, so typos, renames and wrong types surface only at runtime. For known keys use typed readonly properties or 8.4 property hooks; if magic stays, document it with @property-read tags.

open as a page

In PHP 8.4, how do property hooks and virtual properties work, and why can't a readonly class expose a computed passengerName hook?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Since PHP 8.4, get and set hooks attach logic to a property. A property whose hooks never touch its own storage is virtual and takes no memory. Hooked properties cannot be readonly, so readonly classes cannot declare hooks.

open as a page

In a PHP model base class, how do you write a static factory such as User::create() that returns the subclass, and what can break it?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Write create() as return new static(...) with a : static return type, so User::create() builds a User. Guard the constructor signature (final, abstract or interface-declared), because a subclass constructor with different parameters makes new static throw.

open as a page

In a PHP CMS where Article, Page and MediaFile need timestamps and soft deletes, when is a trait the right tool, and how do you stop it becoming hidden coupling?

level: seniorimportance: should knowfreq 30%

basics

~20 s

A trait fits small, cohesive behaviour that several unrelated classes need verbatim, such as timestamp and soft-delete fields. Keep it honest by pairing it with an interface, declaring its needs as abstract methods, and leaving real dependencies to injected services.

open as a page

In PHP, what is an anonymous class created with new class, and when is it a better fit than a named class?

level: middleimportance: nice to knowfreq 30%

basics

~20 s

An anonymous class is declared and instantiated in one new class expression; it can take constructor arguments, extend, implement and use traits. It suits one-off implementations such as test doubles or small adapters, not reusable types.

open as a page

In PHP 8, what is the Stringable interface, when does a class implement it without declaring it, and why type a parameter as string|Stringable?

level: middleimportance: nice to knowfreq 25%

basics

~20 s

Stringable, added in PHP 8.0, is the interface of objects with __toString(). A class that declares __toString() implements it automatically. Typing string|Stringable accepts strings and such objects even under strict_types, where a plain string type rejects objects.

open as a page

In PHP, what do the __debugInfo and __set_state magic methods customise, and which built-in functions call them?

level: middleimportance: nice to knowfreq 14%

basics

~20 s

__debugInfo returns the array var_dump and print_r show for an object, for example to hide a secret. __set_state is a static factory that var_export's output calls when that code is evaluated, rebuilding the object from an array of properties.

open as a page

In PHP 8, which rules does the engine enforce when a class declares magic methods such as __get, __call or __toString?

level: middleimportance: nice to knowfreq 16%

basics

~20 s

Magic methods have fixed parameter counts, no by-reference parameters, and only __callStatic and __set_state may be static. Since PHP 8.0, declared types must also match the documented signatures. A non-public magic method just triggers a warning.

open as a page

After upgrading to PHP 8.1 or later, a class extending ArrayObject logs "Return type of Bag::count() should either be compatible"; what does it mean and how do you fix it?

level: seniorimportance: nice to knowfreq 20%

basics

~10 s

Since PHP 8.1 most non-final internal methods carry tentative return types; an override without a compatible one raises E_DEPRECATED. Declaring the type fixes it; #[\ReturnTypeWillChange] only suppresses the notice until checking becomes strict.

open as a page

showing 31–47 of 47