December Code

PHP OOP interview questions, with answers

Almost all modern PHP, from Laravel and Symfony applications to WordPress plugins, is written with classes, so PHP interviews spend a long time on object-oriented programming. The questions check PHP's own rules as well as general OOP: how constructors and visibility work, what self, static and parent refer to, and how objects are compared and passed around.

The answers below cover constructors, visibility, the three class references, static members, object comparison, instanceof and dependency injection, with code run on PHP 8.5. Then take the free PHP diagnostic — ten questions across every PHP topic in the bank — to see which of these you can explain but not yet predict.

The questions, with answers

  1. 1.How do you define a class with a constructor in PHP?

    In short: Declare properties and a __construct method; since PHP 8, constructor promotion declares and assigns properties in the parameter list.

    A class groups properties and methods, and __construct runs when new creates an object. Constructor property promotion, added in PHP 8.0, lets a constructor parameter with a visibility modifier, such as public string $name, declare the property and assign the argument in one step, so the body is often empty. Parameters can have defaults, as $age does, and a method with no visibility keyword, like this constructor, is public. Properties can carry types, and a typed property without a default must be assigned before it is read. new User("Asha") creates the object, and -> reaches its members.

    class User {
        function __construct(
            public string $name,
            private int $age = 0,
        ) {}
    }
    $u = new User("Asha");
    echo $u->name;
    // Asha
  2. 2.What are public, protected and private in PHP?

    In short: public members are accessible everywhere, protected ones inside the class and its subclasses, and private ones only inside the declaring class.

    Visibility controls who can use a property, method or constant. public is the default for methods and allows access from anywhere. protected allows access from the class and from classes that extend it. private restricts access to the declaring class itself. Reading $w->cash from outside Wallet throws an Error, Cannot access private property, while the public show method can return it. Keeping state private and exposing behaviour through public methods lets a class change its internals without breaking callers. PHP 8.4 added asymmetric visibility, such as public private(set), for read-only access from outside.

    class Wallet {
        private int $cash = 5;
        public function show() {
            return $this->cash;
        }
    }
    $w = new Wallet();
    echo $w->show();
    // 5
    echo $w->cash;
    // throws Error
  3. 3.What is the difference between self, static and parent in PHP?

    In short: self means the class where the code is written, static the class the call was made on (late static binding), and parent the superclass.

    Inside a class, self:: refers to the class in which the method is defined, fixed at compile time. static:: is resolved at run time to the class that was actually called, which is late static binding: a factory in a base class that returns new static() builds an object of the subclass it was called on. parent:: reaches the superclass's version of a method or constant, which is how an overriding method extends rather than replaces the inherited behaviour, as Circle::name does below. self and static give the same answer until inheritance is involved.

    class Shape {
        public function name() {
            return "shape";
        }
    }
    class Circle extends Shape {
        public function name() {
            $p = parent::name();
            return "circle+$p";
        }
    }
    echo (new Circle)->name();
    // circle+shape
  4. 4.What are static properties and methods in PHP?

    In short: Static members belong to the class rather than to an instance: they are reached with ClassName:: and shared by all code that uses the class.

    A static property has one value for the whole class, not one per object, and a static method runs without an object, so it has no $this. Both are reached through the class, as Counter::up() and self::$n inside it. They suit counters, caches and factory methods such as User::fromArray. Because static state is global to the class, it persists across the whole request and makes code harder to test, so frameworks prefer services passed in explicitly. Subclasses share a parent's static property unless they redeclare it.

    class Counter {
        public static int $n = 0;
        static function up() {
            return ++self::$n;
        }
    }
    Counter::up();
    echo Counter::up();
    // 2
  5. 5.How does PHP compare objects with == and ===?

    In short: == is true when two objects are of the same class with equal properties; === is true only when both variables refer to the same instance.

    Comparing objects with == checks that they are instances of the same class and that their properties are equal, compared with == themselves, so two separately created P(1) objects are equal. === checks identity: it is true only if both operands are the same object, which two separate new expressions never are. That mirrors how objects are passed: variables hold handles, and assigning $b = $a makes $a === $b true. For value objects, a custom equals method often expresses the intended comparison more clearly than ==.

    class P {
        function __construct(
            public int $x,
        ) {}
    }
    $a = new P(1);
    $b = new P(1);
    var_dump($a == $b, $a === $b);
    // bool(true)
    // bool(false)
  6. 6.What does instanceof check in PHP?

    In short: $obj instanceof Name is true when the object is of that class, a subclass of it, or implements that interface.

    instanceof tests an object's type at run time. It is true for the object's own class, for any class it extends, and for any interface it implements, directly or through a parent, so a Dog that implements Named is an instance of Named. It is false for non-objects rather than an error, so it is safe on mixed values. Type declarations do the same check automatically for parameters, which is why explicit instanceof checks mostly appear where a value arrives as mixed, such as in a catch-all handler or a factory.

    interface Named {}
    class Dog implements Named {}
    $d = new Dog();
    var_dump($d instanceof Named);
    // bool(true)
  7. 7.What is dependency injection in PHP?

    In short: A class receives the objects it depends on, usually through its constructor, instead of creating them itself, so they can be swapped for tests.

    Signup below needs something that sends mail. Instead of calling new SmtpMailer inside, it declares a Mailer interface parameter in its constructor, and the caller passes an implementation in. Production code passes a real mailer, and a test passes a Fake that records calls, with no change to Signup. Depending on an interface rather than a concrete class keeps components loosely coupled. Frameworks such as Laravel and Symfony provide containers that build these objects and inject their dependencies automatically, using the constructor's type declarations.

    interface Mailer {
        public function send();
    }
    class Fake implements Mailer {
        public function send() {
            return "sent";
        }
    }
    class Signup {
        function __construct(
            private Mailer $m,
        ) {}
        function run() {
            echo $this->m->send();
        }
    }
    $s = new Signup(new Fake());
    $s->run();
    // sent

How the diagnostic asks it

One question from the PHP bank, exactly as a sitting would show it. The bank has 4 on classes & objects and 30 across PHP.

Classes & Objects · mediumPHP-016

What does this PHP code print?

class A {
    public static function make() {
        return new static();
    }
    public static function makeSelf() {
        return new self();
    }
}
class B extends A {}
echo get_class(B::make()), " ", get_class(B::makeSelf());
  1. 1A A
  2. 2B B
  3. 3B Acorrect
  4. 4A B

self always refers to the class in which the method is written, A, so new self() creates an A even when called as B::makeSelf(). static is resolved at run time to the class the method was called on, which is late static binding: B::make() runs A's make with static meaning B, so it creates a B. The output is B A. A A treats static like self. B B treats self like static. A B has them the wrong way round. new static is how factory methods in a base class build the right subclass.

Measure it

Reading answers tells you what’s true. A diagnostic tells you what you get wrong.

10 PHP questions across its topics, easy to hard, about fifteen minutes. You get a readiness figure with the arithmetic shown, the topics you missed named, and a practice set sized for today. Free: 1 diagnostic a month and 15 problems a day. No card.

What the readiness test measures · how the score is computed

By Harshit · updated