Skip to the content.

PHP Interview Questions (all level)

There is an interview tomorrow? Is it your first time or are you a senior? Don’t worry. Here is a cheat sheet to do the best on your interview and refresh your memory.

Questions


What are magic methods? Tell me 3 magic methods.

PHP provides a number of ‘magic’ methods that allow you to do some pretty neat tricks in object-oriented programming. These methods, identified by a two underscore prefix (__), function as interceptors that are automatically called when certain conditions are met.


PHP support multiple inheritance?

PHP do not support multiple inheritance. To allow this feature, you can use interfaces in PHP or you can use “Traits” in PHP instead of classes for implementing multiple inheritance in PHP.


Interface vs abstract class, tell me the diference.

An interface is an OOP element that groups a set of function declarations without implementing them, that is, it specifies the name, return type, and arguments, but not the block of code.

An interface is always an agreement or a promise. When a class says “I implement interface Y”, it is saying “I promise to have the same public methods that any object with interface Y has”.

    //This is saying that "X" agrees to speak the language "Y" with your code.
    class X implements YInterface { }
    interface YInterface
    {
        // You can't define functionality here for methods (just in class X), these are just skeletons.
        public function setVariable($name, $var);
        public function getHtml($template);
    }

On the other hand, an Abstract Class is like a partially built class. It is much like a document with blanks to fill in.

An abstract class is the foundation for another object. When a class says “I extend abstract class Y”, it is saying “I use some methods or properties already defined in this other class named Y”.

    // this is saying that "X" is going to complete the partial class "Y".
    class X extends YAbstract { }
    abstract class YAbstract
    {
        // These are just skeletons like in the YInterface
        abstract protected function setVariable($name, $var);
        abstract protected function getHtml($template);

        // But in an abstract class you can give functionality for the method.
        public function printOut() {
            print $this->getValue() . "\n";
        }
    }

Very important point: In an abstract class you can predefine the working method, but you can’t in an interface.


What the final keyword does?

If you prefix a function in a class with the final keyword, the child class cannot overwrite that function.

class BaseClass {
   final public function moreTesting() {
       echo "BaseClass::moreTesting() called\n";
   }
}

class ChildClass extends BaseClass {
   public function moreTesting() {
       echo "ChildClass::moreTesting() called\n";
   }
}
// Results in Fatal error: Cannot override final method BaseClass::moreTesting()
// You cannot override final methods even if they are defined as private.

What does the following code?

function foo(&$var)
{
    $var++;
}

$a = 5;
$b = $a;
$c = $a + 7;

foo($a);

echo $a;
echo $b;
echo $c;
echo $a;

6

echo $b;

5

echo $c;

12


What are namespaces and how to use them?

Namespaces in PHP prevent naming conflicts by encapsulating entities like classes, interfaces, functions, and constants. They’re like directories for file systems, ensuring that two classes with the same name can coexist if they’re in different namespaces.

To declare a namespace, you use the namespace keyword at the top of your PHP file, before any non-comment code. Here’s a brief example:

namespace MyProject\Database;

class Connection {}
// Using the class from another file
$connection = new \MyProject\Database\Connection();

Explain what are closures?

A closure in PHP is an anonymous function that can capture variables from its surrounding scope. This means you can create a function without a name and pass it around as if it were a regular variable. Closures are useful for creating callback functions.

The use keyword is specifically related to closures in PHP. It allows you to inherit variables from the parent scope (where the closure is defined) into the closure itself. It’s important because, by default, the inner function (closure) does not have access to the outer scope’s variables.


$message = 'Hello';

$exampleClosure = function() use ($message) {
    echo $message;
};

$exampleClosure(); // Outputs 'Hello'

Tell what we need to know about error handling in PHP

Error Types:

Error Reporting

set_error_handler()


function customErrorHandler($errno, $errstr, $errfile, $errline) {
    echo "Error: [$errno] $errstr - $errfile:$errline";
    // Save error to a log file or database
    return true; // To prevent PHP's default error handler from running
}

set_error_handler("customErrorHandler");

// $errno - holds the level of the error.
// $errstr - holds the error message.
// $errfile - holds the filename in which the error occurred.
// $errline - holds the line number in the file where the error occurred.


Explain SOLID with examples

Single Responsibility principle

The Single Responsibility Principle means each class should have just one job. Think of it like a worker in a team, where every person has their own clear task. This keeps things simple and organized, making it easier to manage and update the system.

class User {
    function getUserData() { /* ... */ }
    function saveUserData() { /* ... */ }
}

class UserReportGenerator {
    function generateReport(User $user) { /* ... */ }
}

Open/Closed Principle

The Open/Closed Principle is about designing your classes so that they are open for extension but closed for modification. In simpler terms, it means you should be able to add new features or behaviors to a class without changing its existing code.

interface Shape {
    public function area();
}

class Circle implements Shape {
    private $radius;

    public function area() {
        return pi() * $this->radius * $this->radius;
    }
}

class Square implements Shape {
    private $length;

    public function area() {
        return $this->length * $this->length;
    }
}

Liskov Substitution Principle

The Liskov Substitution Principle ensures that objects of a superclass can be replaced with objects of its subclasses without affecting the application’s correctness.

It’s like saying, if you have a program that uses a bird, you should be able to swap in a different kind of bird, like a sparrow or a pigeon, and everything should still work just fine. It ensures that a subclass can stand in for its parent class without any errors or unexpected behavior.


// In this setup, Bird is the superclass. Sparrow and Penguin are subclasses.
// According to LSP, you should be able to replace instances of Bird with instances of its subclasses (Sparrow or Penguin) without altering the correctness of the program.

class Bird {
    public function fly() {
        echo "I can fly!";
    }
}

class Sparrow extends Bird {
    // Sparrow flies, so no need to override fly()
}

class Penguin extends Bird {
    public function fly() {
        throw new Exception("I can't fly!");
    }
}

function makeBirdFly(Bird $bird) {
    $bird->fly();
}

$bird1 = new Sparrow();
$bird2 = new Penguin();

makeBirdFly($bird1); // Works fine
makeBirdFly($bird2); // Error: breaks LSP


Interface Segregation Principle

It means designing your interfaces in such a way that your classes don’t have to implement methods they don’t need. It encourages splitting large, multipurpose interfaces into smaller, more specific ones so that clients only need to know about the methods that are of interest to them. This leads to a cleaner, more organized codebase and reduces the impact of changes.

// Split into two interfaces: Workable and Eatable. Classes implement only the interfaces that are relevant to them.

interface Workable {
    function work();
}

interface Eatable {
    function eat();
}

class HumanWorker implements Workable, Eatable {
    function work() { /* ... */ }
    function eat() { /* ... */ }
}

class RobotWorker implements Workable {
    function work() { /* ... */ }
    // No need to implement eat()
}

Dependency Inversion Principle

DIP is focusing on decoupling high-level modules from low-level modules by introducing an abstraction layer.

// Imagine you have a TV remote (the UserDataProcessor) that needs batteries (the DatabaseInterface) to work.
// It doesn't matter what brand of batteries you use (like MySQLDatabase or any other database), as long as they fit the remote.

interface DatabaseInterface {
    function fetchData();
}

class MySQLDatabase implements DatabaseInterface {
    function fetchData() { /* ... */ }
}

class UserDataProcessor {
    private $database;

    function __construct(DatabaseInterface $db) {
        $this->database = $db;
    }

    function processData() {
        $data = $this->database->fetchData();
        // process data
    }
}

Explain Dependency Injection

Dependency Injection (DI) in PHP is like giving a class its ‘tools’ from outside rather than building them inside. It makes your code flexible (easy to change), clear (easy to understand), and test-friendly (easy to check if it’s working).

// without DI
class Car {
    private $engine;
    
    public function __construct() {
        $this->engine = new Engine(); // The Car class is directly dependent on the Engine class.
    }
}

// with DI

class Car {
    private $engine;
    
    public function __construct(Engine $engine) {
        $this->engine = $engine; // The Engine dependency is injected into the Car class.
    }
}

// Creating an Engine instance and injecting it into the Car class.
$engine = new Engine();
$car = new Car($engine);

Composition vs Inheritance

Most of the time use composition over inheritance because composition is much more flexible.

Detailed explonation

Inheritance example code

<?php

class Image {
    protected $filename;
    protected $size;

    public function __construct($filename) {
        $this->filename = $filename;
    }

    public function setSize($size) {
        $this->size = $size;
    }

    public function getSize() {
        return $this->size;
    }

    // A general method for preparing an image. It could be overridden by subclasses.
    public function prepareForSave() {
        echo "Preparing image for save. Filename: " . $this->filename . "\n";
    }
}

class PngImage extends Image {
    // Specific implementation for PNG images
    public function prepareForSave() {
        $this->setSize("1024x768");
        echo "Preparing PNG image for save. Size set to: " . $this->getSize() . ". Filename: " . $this->filename . "\n";
    }
}

class JpegImage extends Image {
    // Specific implementation for JPEG images
    public function prepareForSave() {
        $this->setSize("800x600");
        echo "Preparing JPEG image for save. Size set to: " . $this->getSize() . ". Filename: " . $this->filename . "\n";
    }
}

class BmpImage extends Image {
    // Specific implementation for BMP images
    public function prepareForSave() {
        $this->setSize("640x480");
        echo "Preparing BMP image for save. Size set to: " . $this->getSize() . ". Filename: " . $this->filename . "\n";
    }
}

// Example Usage
$png = new PngImage("example.png");
$png->prepareForSave();

$jpeg = new JpegImage("example.jpeg");
$jpeg->prepareForSave();

$bmp = new BmpImage("example.bmp");
$bmp->prepareForSave();

Composition example code

class Image {
    protected $filename;
    protected $size;

    public function __construct($filename) {
        $this->filename = $filename;
    }

    public function setSize($size) {
        $this->size = $size;
    }

    public function getSize() {
        return $this->size;
    }
}

interface ImageSaver {
    public function prepareForSave();
}

class PngImage implements ImageSaver {
    protected $image;

    // Dependency Injection through the constructor
    public function __construct(Image $image) {
        $this->image = $image;
    }

    public function prepareForSave() {
        $this->image->setSize("1024x768");
        echo "Preparing PNG image for save. Size set to: " . $this->image->getSize() . "\n";
    }
}

class JpegImage implements ImageSaver {
    protected $image;

    // Dependency Injection through the constructor
    public function __construct(Image $image) {
        $this->image = $image;
    }

    public function prepareForSave() {
        $this->image->setSize("800x600");
        echo "Preparing JPEG image for save. Size set to: " . $this->image->getSize() . "\n";
    }
}

// Example Usage
$pngImage = new Image("example.png");
$png = new PngImage($pngImage);
$png->prepareForSave();

$jpegImage = new Image("example.jpeg");
$jpeg = new JpegImage($jpegImage);
$jpeg->prepareForSave();