Optional Type Declarations in PHP: Enhancing Code Reliability

Updated: January 9, 2024 By: Guest Contributor Post a comment

Introduction

PHP, widely known for its leniency in type declarations, has been adopting features enhancing code reliability. Optional type declarations, introduced in PHP 7, serve as instruments for cleaner, clearer, and more robust codebases.

Getting Started with Types

Type declarations, also known as type hints, allow developers to specify the expected data type of arguments in function calls, return types from functions, and class properties. Here’s a quick example:

function add(int $a, int $b): int {
    return $a + $b;
}

This function mandates that both parameters must be integers, and it will return an integer as well.

Scalar Type Declarations

Scalar types were a significant addition in PHP 7. They allow functions to require parameters to be of type int, float, string, or bool. Here’s how you can use them:

function setAge(int $age) {
    echo "You are {$age} years old.";
}

Strict vs. Coercive Typing

PHP 7 introduced a strict typing mode. This is enabled by declaring declare(strict_types=1); at the top of the file, which forces PHP to adhere to the specified types otherwise it will throw a TypeError. Here’s the difference in behavior:

// Coercive mode
function addNumbers($a, $b): int {
    return $a + $b;
}

addNumbers('3', 4.2); // This will work, outputting 7

// Strict mode
declare(strict_types=1);

function addNumbersStrict($a, $b): int {
    return $a + $b;
}

addNumbersStrict('3', 4.2); // TypeError

In coercive mode, PHP will juggle types to match the declaration if possible, while in strict mode, it will not.

Union Types

PHP 8 brings union types, allowing a parameter or return type to accept multiple types. This is particularly useful in polymorphic scenarios:

function processInput(string|int $data) {
    if (is_int($data)) {
        echo "Integer received: $data";
    } else {
        echo "String received: $data";
    }
}

Complex Types: Arrays and Objects

Beyond scalar types, PHP allows for complex type declarations such as arrays and objects. Here’s how these might be used:

function configure(array $settings) {
    // Process settings array
}

class User {}

function newUser(User $user) {
    // Process User object
}

Nullables and Defaults

Nullables, designated by a question mark before the type declaration, allow the parameter to be either of the specified type or null. Here’s how to employ nullables:

function setProfile(string $name, ?string $bio) {
    if (is_null($bio)) {
        echo "Welcome, $name!";
    } else {
        echo "Welcome, $name! Read their bio: $bio";
    }
}

Property Type Declarations

With PHP 7.4, property type declarations were introduced, providing the ability to declare types for class and object properties. Example:

class Item {
    public int $id;
    public string $name;
}

Advanced: Variadics and Types

Variadic functions can also utilize type declarations, ensuring all values passed into a variable-length argument list are of the same type:

function addAll(int ...$numbers): int {
    return array_sum($numbers);
}

Using Types in Anonymous Functions

Anonymous functions, also known as closures, can benefit from type declarations as follows:


$arrayOfNumbers = [1, 2, 3];

$arrayOfNumbers = array_map(
   function (int $number): int {
       return $number * 2;
   },
   $arrayOfNumbers
);

Backward Compatibility

New type declarations are generally backward compatible, but introducing them to legacy code should be done cautiously. Type errors may arise in code where informal typing was previously used.

Conclusion

Type declarations in PHP enhance the robustness and clarity of code. They introduce a layer of reinforcing the developer’s intent and making sure the code works as expected. With a number of options that scale from scalar to complex types, there’s a valuable set of tools at one’s disposal for writing clean, predictable PHP code.