PHP OOP interview questions and answers for PHP 8.5
Thirty-three PHP OOP interview questions with answers and code run on PHP 8.5: classes, inheritance, interfaces, polymorphism, traits, visibility, magic methods, cloning and SOLID.
Updated 18 min read

In this article
PHP object-oriented programming questions test whether you can design classes that are easy to change: clear interfaces, small classes, composition before inheritance, and the language features PHP 8 added to make objects safer. Interviewers still ask the classic definitions, such as the four pillars, abstract classes versus interfaces and access modifiers, but they expect answers that match how PHP works today, not how PHP 5 worked.
Updated for PHP 8.5 (8.5.11 is the current release in October 2026). This article keeps the classic PHP OOP question set, corrects the answers that were wrong or out of date, and adds the OOP questions that now come up. Every code example below was run on PHP 8.5.7, and the outputs shown are from those runs.
Two related articles cover neighbouring ground, so their questions are not repeated here: PHP interview questions for 2026 (language basics, match, property hooks, the pipe operator, self versus static, generators and Fibers) and PHP enums and readonly classes.
PHP and OOP basics
1. What is PHP used for?
PHP is a general-purpose scripting language used mainly for server-side web development: rendering pages, building APIs, processing forms, talking to databases and running background jobs from the command line. WordPress, Drupal, Magento, Laravel, Symfony and many SaaS products are written in it. It runs behind a web server through PHP-FPM, or as a long-running process with application servers such as FrankenPHP or RoadRunner.
2. Is PHP an object-oriented language?
PHP is multi-paradigm: you can write procedural, object-oriented or functional-style code. Its object model has been complete since PHP 5 (2004): classes, interfaces, abstract classes, visibility, exceptions and late static binding. PHP 5.4 added traits, PHP 7 added scalar and return types, and PHP 8 added constructor promotion, attributes, enums, readonly properties, property hooks and more. Modern frameworks are almost entirely object-oriented.
3. What are the advantages of PHP?
- Easy to deploy: almost every host supports it, and each request starts with a clean state, so a memory leak or crash rarely affects other requests.
- Mature ecosystem: Composer and Packagist, PHPUnit and Pest, PHPStan and Psalm, and well-documented frameworks.
- Good performance on PHP 8 with OPcache, and an optional JIT.
- A gradual type system you can tighten with
declare(strict_types=1)and static analysis. - A large hiring pool and long-lived applications that still need maintaining.
4. What is object-oriented programming?
OOP organises a program around objects that combine data (properties) and behaviour (methods). Instead of passing arrays to functions that know their structure, you ask objects to do things, and each object protects its own rules. In PHP terms: an Order object knows how to add a line and calculate its total, and nothing else can put it into an invalid state.
5. What are the key characteristics of OOP?
The four usual pillars:
- Encapsulation: keep data private and expose behaviour through methods.
- Abstraction: expose what an object does, not how.
- Inheritance: a class can extend another and reuse or change its behaviour.
- Polymorphism: code works with any object that fulfils a contract.
A strong answer adds that in practice you favour composition (objects holding other objects) over deep inheritance, and that interfaces carry most of the weight in polymorphism.
6. What are a class and an object?
A class is a definition: the properties and methods that objects of that type have. An object is an instance created with new, holding its own property values. Circle is a class; new Circle(1.5) is an object. Objects are passed by handle: assigning an object to another variable or passing it to a function does not copy it, both variables refer to the same object. Use clone to copy.
7. What are member variables and member functions?
Member variables, called properties in PHP, hold an object's state; member functions, called methods, define its behaviour. Both have a visibility and may be static. Since PHP 7.4 properties can be typed, since 8.1 readonly, and since 8.4 they can have hooks and asymmetric visibility. Declare every property: creating properties dynamically on a normal class is deprecated since PHP 8.2.
Inheritance, interfaces and polymorphism
8. What is inheritance?
Inheritance lets a child class extend a parent with extends, reusing its public and protected members and overriding methods. PHP has single inheritance: a class extends at most one parent, but can implement many interfaces and use many traits. Inheritance expresses "is a" (a Circle is a Shape); if you only want to reuse code, composition or a trait is usually better, because deep hierarchies are hard to change. Mark classes final unless you designed them to be extended.
9. What is polymorphism? Give an example.
Polymorphism means one interface, many implementations: code that depends on a type works with any class that implements it. Below, totalArea() knows only the Shape interface, and each class supplies its own area().
<?php
declare(strict_types=1);
interface Shape
{
public function area(): float;
}
abstract class NamedShape implements Shape
{
public function describe(): string
{
return sprintf('%s with area %.2f', static::class, $this->area());
}
}
final class Circle extends NamedShape
{
public function __construct(private float $radius) {}
public function area(): float
{
return M_PI * $this->radius ** 2;
}
}
final class Rectangle extends NamedShape
{
public function __construct(private float $width, private float $height) {}
public function area(): float
{
return $this->width * $this->height;
}
}
/** @param list<Shape> $shapes */
function totalArea(array $shapes): float
{
return array_sum(array_map(fn (Shape $s) => $s->area(), $shapes));
}
$shapes = [new Circle(1.5), new Rectangle(2, 3)];
foreach ($shapes as $shape) {
echo $shape->describe(), PHP_EOL;
}
printf("Total: %.2f\n", totalArea($shapes));Output on PHP 8.5.7:
Circle with area 7.07
Rectangle with area 6.00
Total: 13.07Adding a Triangle needs no change to totalArea(): that is the open/closed principle in practice.

10. What types of polymorphism are there, and which does PHP support?
Textbooks distinguish compile-time polymorphism (method overloading: several methods with the same name and different parameters) from run-time polymorphism (overriding: the method that runs depends on the object's class). PHP supports run-time polymorphism through inheritance and interfaces. It does not support method overloading: declaring two run() methods in one class is a fatal error ("Cannot redeclare A::run()"). You get similar effects with optional parameters, union types, named arguments or variadics, and, rarely, the magic __call() method. Generics (parametric polymorphism) exist only in docblocks, checked by PHPStan or Psalm.
11. What is an interface?
An interface declares public methods a class must implement, without implementation. A class implements it with implements, and can implement several. Interfaces can declare constants and, since PHP 8.4, properties with hook requirements such as public string $sku { get; }. Type-hint against interfaces (PaymentGateway) rather than concrete classes (StripeGateway), so you can swap implementations and use test doubles.
<?php
interface HasSku
{
public const string PREFIX = 'SKU-';
public string $sku { get; }
}
final class Product implements HasSku
{
public function __construct(private string $code) {}
public string $sku { get => self::PREFIX . $this->code; }
}
echo (new Product('42'))->sku; // SKU-4212. What are the differences between abstract classes and interfaces?
| Abstract class | Interface | |
|---|---|---|
| Instantiable | No | No |
| Implementation | Can have concrete methods, constructor and state | No method bodies (property hooks may be declared, not implemented) |
| Properties | Any visibility, typed, with defaults | Only public hooked property declarations (8.4+) |
| Visibility of methods | public, protected, private (abstract ones public or protected) | public only |
| How many per class | One (single inheritance) | Many |
| Constants | Yes | Yes |
When to choose each, and how traits fit in, is covered in our PHP interview questions for 2026. The short version: an interface is a contract; an abstract class is a partly built implementation of one.
13. What are traits for?
A trait is a group of methods (and properties) copied into a class with use, giving horizontal code reuse without inheritance. Traits suit small, cross-cutting behaviour such as timestamps. They cannot be instantiated or type-hinted, so they do not replace interfaces. When two traits define the same method, resolve the conflict explicitly:
<?php
trait Timestamps
{
public ?DateTimeImmutable $updatedAt = null;
public function touch(): void { $this->updatedAt = new DateTimeImmutable('2026-10-10 09:00'); }
}
trait Loggable
{
public function touch(): void { echo "logged\n"; }
}
final class Post
{
use Timestamps, Loggable {
Timestamps::touch insteadof Loggable;
Loggable::touch as logTouch;
}
}
$p = new Post();
$p->touch();
$p->logTouch();
echo $p->updatedAt->format('Y-m-d H:i'), PHP_EOL;Output: logged then 2026-10-10 09:00. Overusing traits hides dependencies and makes classes hard to read, so prefer injecting a collaborator when the behaviour needs its own state or configuration.
14. What is the final keyword?
final on a class prevents extension; on a method prevents overriding; on a class constant (since 8.1) prevents redefinition in children. PHP 8.5 also allows final on promoted constructor properties. Making classes final by default keeps your public surface small and lets you change internals safely; open them deliberately when extension is part of the design.
15. What is the #[\Override] attribute?
Added in PHP 8.3, #[\Override] on a method tells PHP the method must override a parent or interface method. If the parent method is renamed or you misspell the name, PHP fails at compile time instead of silently creating a new method. In our test, a typo produced: Fatal error: Child::handel() has #[\Override] attribute, but no matching parent method exists. PHP 8.5 extends the attribute to properties.
Encapsulation, visibility and class members
16. What are the access modifiers in PHP?
public: accessible from anywhere.protected: accessible in the class, its parents and its children.private: accessible only in the declaring class.
Visibility applies to properties, methods and constants. Properties and methods without a modifier are public (for methods; properties need a modifier or a type with var, which is legacy). PHP 8.4 added asymmetric visibility such as public private(set), and PHP 8.5 extends it to static properties; see the 2026 article for details. Default to private and widen only when needed.
17. What is the difference between encapsulation and abstraction?
Encapsulation is about protection: an object hides its data and enforces its own rules, so other code cannot put it into an invalid state. Abstraction is about simplification: callers see a small, meaningful interface and do not need to know the implementation. A Money class encapsulates by keeping amounts in integer cents and refusing to add different currencies; it abstracts by offering add() instead of exposing arithmetic and rounding rules.
<?php
final class Money implements Stringable
{
public function __construct(public readonly int $cents, public readonly string $currency) {}
public function add(Money $other): self
{
if ($other->currency !== $this->currency) {
throw new InvalidArgumentException('Currency mismatch');
}
return new self($this->cents + $other->cents, $this->currency);
}
public function __toString(): string
{
return sprintf('%s %.2f', $this->currency, $this->cents / 100);
}
}
$a = new Money(1050, 'USD');
$b = new Money(1050, 'USD');
var_dump($a == $b, $a === $b);
echo $a->add($b), PHP_EOL;
try { $a + $b; } catch (TypeError $e) { echo get_class($e), ': ', $e->getMessage(), PHP_EOL; }Output on PHP 8.5.7:
bool(true)
bool(false)
USD 21.00
TypeError: Unsupported operand types: Money + MoneyThis also answers a common follow-up: == on objects compares class and property values, while === checks whether both variables refer to the same instance.
18. Does PHP support operator overloading?
Not for your own classes. As the output above shows, $a + $b on two objects throws a TypeError. Some internal classes overload operators (for example GMP numbers and DateTime comparisons), and an RFC for userland operator overloading was declined in 2022. You get similar convenience with explicit methods such as add(), the __toString() method for string conversion, and interfaces such as ArrayAccess, Countable and IteratorAggregate that let objects behave like arrays in specific ways.
19. What is the static keyword for?
Static properties and methods belong to the class rather than an instance: Counter::created() works without an object, and a static property is shared by all instances. Inside a class, self:: refers to the class where the code is written. Static members suit pure helpers and named constructors (Money::fromString()), but static state is global state: it survives between tests and, in long-running workers, between requests, so avoid it for anything mutable.
<?php
class Counter
{
private static int $created = 0;
public const string PREFIX = 'C-';
public function __construct(public readonly string $id = '')
{
self::$created++;
}
public static function created(): int
{
return self::$created;
}
}
new Counter(); new Counter();
echo Counter::created(), ' ', Counter::PREFIX, PHP_EOL;Output: 2 C-. (Typed class constants such as const string need PHP 8.3 or newer.)
20. What are the types of constructors in PHP?
PHP has exactly one constructor per class, __construct(). Languages like Java distinguish default, parameterised and copy constructors; in PHP you get the same effects with default parameter values, named arguments, static named constructors such as Money::fromCents(), and clone with __clone() instead of a copy constructor. Since PHP 8.0, constructor property promotion declares and assigns properties in the signature, as in the examples above. PHP 4-style constructors (a method named after the class) stopped working as constructors in PHP 8.0.
21. Is there a finalize() method in PHP?
No. finalize() is a Java concept. PHP has __destruct(), which runs when the last reference to an object disappears, or at the end of the script. Because PHP uses reference counting, that moment is predictable for simple cases:
<?php
final class TempFile
{
public function __construct(public readonly string $path) { touch($path); echo "created\n"; }
public function __destruct() { @unlink($this->path); echo "removed\n"; }
}
function work(): void { $f = new TempFile(sys_get_temp_dir() . '/demo.tmp'); echo "working\n"; }
work();
echo "after\n";Output: created, working, removed, after, so the destructor ran when work() returned. Objects caught in reference cycles are only collected later by the cycle collector, so do not rely on destructors for critical work such as committing transactions; use explicit methods and try/finally. Do not confuse this with the final keyword.
22. What are magic methods?
Methods with a double-underscore name that PHP calls automatically: __construct(), __destruct(), __get() and __set() (inaccessible properties), __isset(), __unset(), __call() and __callStatic() (inaccessible methods), __toString(), __invoke() (calling an object like a function), __clone(), __serialize() and __unserialize(), __set_state() and __debugInfo(). In PHP 8.5, __sleep() and __wakeup() are soft-deprecated in favour of __serialize() and __unserialize(). Use magic methods sparingly: they hide behaviour from IDEs and static analysis.
<?php
final class Greeter
{
public function __call(string $name, array $args): string
{
return match ($name) {
'hello' => 'Hello, ' . ($args[0] ?? 'world'),
default => throw new BadMethodCallException("Unknown method $name"),
};
}
}
$g = new Greeter();
echo $g->hello(), ' | ', $g->hello('Sam'), PHP_EOL;23. What is the difference between a shallow and a deep copy, and what does clone with add?
clone makes a shallow copy: scalar properties are copied, but object properties still point to the same objects. Implement __clone() to copy nested objects. PHP 8.5 lets you pass new property values to clone(), which makes "with-er" methods on readonly classes one line:
<?php
final class Address { public function __construct(public string $city) {} }
final class Customer
{
public function __construct(public string $name, public Address $address) {}
public function __clone()
{
$this->address = clone $this->address; // deep copy the nested object
}
}
$a = new Customer('Ana', new Address('Leeds'));
$b = clone $a;
$b->address->city = 'York';
echo $a->address->city, ' / ', $b->address->city, PHP_EOL;
readonly class Point
{
public function __construct(public int $x, public int $y) {}
public function withX(int $x): static
{
return clone($this, ['x' => $x]);
}
}
$p = new Point(1, 2);
$q = $p->withX(5);
echo "{$p->x},{$p->y} -> {$q->x},{$q->y}", PHP_EOL;Output: Leeds / York and 1,2 -> 5,2. Without the __clone() method, both customers would have shown York.
Namespaces, types and other language questions
24. What are namespaces, and why are they used?
Namespaces group classes, interfaces, functions and constants under a name such as App\Billing, so two libraries can each have a Client class without conflict. Import names with use, and alias them with as when needed. Composer's PSR-4 autoloader maps namespaces to directories (App\ to src/), so the file path follows the class name and no require calls are needed. Unqualified function calls fall back to the global namespace; class names do not.
25. What is the significance of the null type?
null is a type with one value, meaning "no value". A variable is null if assigned null, never assigned, or unset. In declarations, ?Address or Address|null marks a nullable type, and since 8.2 null, true and false can be standalone types. Prefer avoiding null where you can: a Customer that always has an Address is simpler to use. Where null is valid, the nullsafe operator ?-> and null coalescing ?? keep checks short. Accessing a method on null throws an Error.
26. What is the difference between echo and print?
Both are language constructs that output strings. echo takes one or more comma-separated arguments and returns nothing; print takes one argument and returns 1, so it can be used in expressions. echo is marginally faster and far more common. When an object is echoed, PHP calls its __toString() method; without one, it throws an Error.
27. What is the difference between require and include?
require stops the script with a fatal error if the file is missing; include only emits a warning. The _once variants skip files already loaded. In object-oriented code you rarely call them for classes, because Composer's autoloader loads classes on first use. The 2026 article covers this question in more depth.
28. What does yield do?
yield turns a function into a generator that produces values one at a time, keeping memory flat when processing large data sets. A class can return a generator from getIterator() to implement IteratorAggregate cheaply. Generator details and examples are in our 2026 PHP questions.
Design questions interviewers now add
29. What are the SOLID principles?
- Single responsibility: a class has one reason to change.
- Open/closed: add behaviour with new classes rather than editing stable ones, as with
Shapeabove. - Liskov substitution: a subclass must work wherever its parent is expected. PHP enforces part of this: parameter types may be widened (contravariance) and return types narrowed (covariance), never the reverse.
- Interface segregation: several small interfaces beat one large one.
- Dependency inversion: depend on interfaces, and let a container or factory supply implementations.
30. Composition or inheritance?
Prefer composition: give a class the collaborators it needs (new OrderService($gateway, $mailer)) rather than inheriting behaviour from a base class. Composition keeps classes small, lets you swap parts in tests, and avoids the "fragile base class" problem in which a change to a parent breaks children you did not know existed. Use inheritance for true subtypes and framework extension points.
31. What is dependency injection?
Passing an object's dependencies to it, usually through the constructor, instead of creating them inside. It makes dependencies visible, lets tests pass fakes, and lets configuration choose implementations. A dependency injection container (Laravel's, Symfony's, PHP-DI) automates the wiring by reading constructor types. The opposite, a service locator (calling a global container from inside a class), hides dependencies and is usually discouraged.
32. What are anonymous classes?
Classes without a name, created inline with new class(...) extends Base implements Contract { ... }. They are handy for one-off implementations, especially test doubles and small adapters. In our test, new class('Sales') extends Report { ... } implemented an abstract method and printed Sales: 3 rows.
33. What OOP-related additions in PHP 8.5 should you know?
clone()with property overrides, shown above.finalon promoted constructor properties.#[\Override]on properties, and#[\Deprecated]on traits and constants.- Asymmetric visibility for static properties.
#[\NoDiscard]: PHP warns when a marked return value is ignored, unless you cast the call to(void). In our test, callingsave();gave "The return value of function save() should either be used or intentionally ignored by casting it as (void)", and(void) save();did not.- Static closures and first-class callables in constant expressions, such as attribute arguments.
Upgrading a large OOP codebase across several PHP versions is mostly about finding the deprecations that tests do not catch. Cloudsoft Zone's Laravel and PHP development service handles PHP upgrades with static analysis and test coverage first.
How to prepare
Write a small domain model without a framework: an Order with lines, a Money value object, a PaymentGateway interface with a fake implementation, and PHPUnit tests. Run PHPStan at a high level on it. Then explain each design choice out loud: why final, why an interface, why the constructor takes those arguments. Interviewers care more about that reasoning than about textbook definitions. Our PHPStan tutorial and property hooks tutorial are good next steps.
Need a PHP application designed cleanly, refactored or upgraded to PHP 8.5? Cloudsoft Zone builds and maintains Laravel and PHP applications, with typed, tested code that your team can keep extending.
Frequently asked questions
Does PHP support method overloading?
No. Declaring two methods with the same name in one class is a fatal error. Use optional parameters, union types, named arguments or separate method names instead.
Does PHP support multiple inheritance?
Not for classes: a class extends at most one parent. It can implement many interfaces and use many traits, which covers most needs.
Is there a finalize() method in PHP?
No. PHP has
__destruct(), which runs when the last reference to an object is gone. Thefinalkeyword is unrelated: it prevents extending a class or overriding a method.Which PHP version should I prepare OOP answers for?
PHP 8.4 or 8.5. Know constructor promotion, readonly properties, enums, property hooks,
#[\Override]and the 8.5 additions such asclonewith property overrides.
Your next customer could start right here.
Introduce your tool, product or business to readers exploring technology.
Explore placements and request a private quote
Sources
- PHP 8.5 release announcement — The PHP Group
- PHP Manual: Classes and Objects — The PHP Group
- PHP Manual: Object Interfaces — The PHP Group
- PHP Manual: Traits — The PHP Group
- PHP Manual: Magic Methods — The PHP Group
- PHP Manual: Object Cloning — The PHP Group
- PHP RFC: User Defined Operator Overloads (declined) — PHP Wiki
- PHP 8.5.11 release — The PHP Group, 2026-09-24
Written with substantial AI assistance. Facts checked against cited sources. Editorial policy.
Comments
No comments yet. Be the first to join the conversation.
Leave a comment
Every comment is read by a moderator before it appears. Your email address is never published; it is used only to contact you about this comment.
More from Cloudsoft Zone

Interview preparationInterview questions
PHP interview questions and answers for 2026 (PHP 8.4 and 8.5)
22 PHP interview questions grouped by level, with concise model answers and short examples covering strict types, enums, match, PDO, password hashing, property hooks and the PHP 8.5 pipe operator.
By Cloudsoft Zone

Interview preparationInterview questions
Docker interview questions and answers for Docker Engine 29
18 Docker interview questions from images and volumes to build cache, Compose, networking, signals and the containerd image store, with short model answers.
By Cloudsoft Zone

Industry updateCakePHP
What's new in CakePHP 5.4: ORM changes, DTO mapping and a built-in container
CakePHP 5.4 changes default eager loading, enforces entity-table ownership and adds request-to-DTO mapping, an optional built-in DI container, typed unhydrated queries and JSON streaming. Here is what to check before upgrading.
By Cloudsoft Zone
