MVC Lesson 2: Basic OOP Concepts in modern PHP

In this blog post, we’ll cover some essential basic OOP concepts that every PHP developer should know.

1. One Class Per File: A Standard Practice

A crucial practice in OOP is one class per file. This makes it easier to maintain and organize your code as your application grows. Each class should be defined in its own file, and the file name should match the class name. This helps with consistency and also aligns with PSR-4 Autoloading standards.

Example:
If you have a class Car, it should be in a file named Car.php. Furthermore, the class name should start with an uppercase letter and follow CamelCase formatting.

// File: Car.php
class Car {
    public $color;

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

    public function getColor() {
        return $this->color;
    }
}

This ensures a consistent structure and makes the code more intuitive.

2. Null Safe Operator

The null safe operator is a relatively new feature in PHP (available from PHP 8.0 onwards) that simplifies working with nullable objects. When working with objects, you may need to check whether an object is null before trying to access its properties or methods. With the null safe operator (?->), you no longer need to manually check if the object is set (isset).

Example:
If you’re trying to call a method on an object that may be null, instead of writing:

if (isset($obj)) {
    $obj->method();
}

You can use the null safe operator like this:

$obj?->method();

This will only call the method() if $obj is not null; otherwise, it simply skips the operation. It’s a clean and concise way to avoid checking if objects are set before performing actions on them.

3. Global Namespace

In PHP, namespaces are used to group related classes, interfaces, and functions together. However, sometimes you need to use classes from the global namespace (i.e., not within any specific namespace). In such cases, you can reference the global namespace by using the backslash (\) before the class name.

Example:

$newDate = new \DateTime();

This will create a new instance of the DateTime class from the global namespace, even if your code is inside a namespace.

4. Autoloading Classes with spl_autoload_register()

PHP offers an easy way to autoload classes, meaning that it automatically loads the required class files when they are needed, without the need to manually include or require each file. This is especially helpful in large applications with many classes.

To enable autoloading, you can use the spl_autoload_register() function. In this function, you must convert the namespace separators (\) into directory separators (/) for the correct path.

Example:

spl_autoload_register(function ($class) {
    require_once str_replace('\\', '/', $class) . '.php';
});

In this example, if PHP needs to load a class like App\Models\User, it will search for the file App/Models/User.php and include it. This makes code management cleaner, as PHP automatically loads the classes when needed.

5. Accessing Static Properties with self::

In PHP, static properties belong to the class itself rather than to instances of the class. To access a static property inside the class, you can use the self:: keyword followed by the property name. This ensures that the static property is accessed correctly without needing to create an object.

Example:

class Car {
    public static $wheels = 4;

    public static function getWheels() {
        return self::$wheels;
    }
}

Here, the static property $wheels is accessed using self::$wheels inside the getWheels method.

6. Using Static Methods with the Scope Resolution Operator (::)

In PHP, you can access static methods of a class without needing to instantiate an object. To do this, you use the scope resolution operator (::).

Example:

class Car {
    public static function getInfo() {
        return "This is a car.";
    }
}

// Access static method without creating an object
echo Car::getInfo();

Here, the static method getInfo() is accessed directly through the class name using the :: operator, making it unnecessary to create an instance of Car.