Personal reading notes

Things to remember about OOP

Public properties are not very common and not considered good practice. It’s better to implement getters and setters. (Except for when we’re dealing with class constants as they are read-only by default and therefore safe to be declared as public.)


Dynamically assigned properties are also very uncommon and usually a mistake - they will always be public and untyped:

class SimplePropertyAssignment {
    private string $defined = 'defaultValue';
    public function __construct(
            private string $constructorParam = 'constructorValue'
    ) {
        // bad idea - 'SimplePropertyAssignment->dynamicProperty' will be public and untyped
        $this->dynamicProperty = 'dynamicallyAdded';
    }
}

When a property accesses a variable or constants of its class, this variable or constant is called the backing field of that property.

Interfaces

Interfaces help to make sure that a class has certain methods for sure and that these methods will return certain types. (Specifying the return types is optional though.) Example from W3 Schools:

interface Animal {
  public function makeSound() : string;
}
 
class Cat implements Animal {
  public function makeSound() {
    echo "Meow";
  }
}

Interfaces contain functions with no bodies. Child classes implement interfaces. A class can implement multiple interfaces, but can only be derived from one abstract class.

Encapsulation

Encapsulation enables an object to hide data and functionalities from other pieces of code, for example by making them private. “[T]he general wisdom is that you should keep as much as possible hidden away and only expose the minimum amount of functionality and data in order to maximize your freedom to refactor.” (That means it’s easier to make changes to your code later, when you keep your objects independent from one another. It also prevents internal state of an object from being corrupted.)

There’s three levels of visibility in PHP: private, protected, public. By default, methods and properties of a class will be public. Most of the time this is not desired and one should always set their methods and properties to private or protected. A protected field is only accessible within the class in which it is declared and any class that is derived from it (i.e. child classes).


OO PHP is based on single inheritance - multiple inheritance is not supported -, which means that a child can have only one parent class (or base class), while parents can have multiple children.

Classes that are marked as final cannot be inherited from.

Abstract Classes and Methods

Method is another name for a function of a class (or an instantiated object). The name of a method and its parameters are called signature of a method. However, PHP doesn’t support traditional method overloading, which means a class cannot have multiple methods with the same name, even when their paramteres (and thus their signatures) differ. Thus signatures in PHP don’t play a great role.

Abstract classes can only be parent/base classes for other derived/child classes. They can have fields, methods and properties, but no object can be instantiated directly from an abstract class. Abstract functions/methods can only exist in abstract classes, have no body and must be implemented in the child class.

abstract class MyClass
{
    abstract protected int $foo = 1;
    abstract public function calculateSomething();
}

Variadic functions

PHP supports variadic functions, i.e. functions that accept a non-determined number of arguments

function sum(int ...$nums): int
{
    return array_sum($nums);
}

The opposite of variadic functions are fixed-arity functions.

Enumeration

enum is a data type. “An Enum defines a […] type, which has a fixed, limited number of possible legal values.” (php.net) They’re useful for typechecking.

enum Directions
{
    case Up;
    case Down;
    case Left;
    case Right;
}
 
function go_somewhere(Direction $direction) {
  print $direction;
}
 
$value = Direction::Left;
go_somewhere($value);

There’s pure enums and backed enums. In backed enums cases have a scalar equivalent.

enum Directions
{
    case Up = "U";
    case Down = "D";
    case Left = "L";
    case Right = "R";
}
// this will print "U"
print Directions::Down->value;

Scope

Global namespace

If you want to ensure that a function or a constant that you are using is from the global namespace and doesn’t call a function or constant that accidentally has the same name, but is defined inside the scope of an object for example, you prefix that function or constant with a \, as in this example:

$nonce = \random_bytes(\SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES);

PHP Standards Recommendations

Check https://www.php-fig.org/psr/.

PHP Security Guide

The PHP Security Guide.