PHP 8 Features (Attributes, Enums, Match, Nullsafe Operator)

7 questions found

What is the match expression introduced in PHP 8, and how does it improve upon the traditional switch statement?

Beginner
The match expression compares a value against several possible conditions and returns a corresponding result, similar in purpose to a switch statement, but match uses strict type comparison by default rather than loose comparison, does not require a break statement to prevent falling through to the next case, and can be used directly as an expression that returns a value, making it more concise and less error prone than the equivalent switch statement for many common use cases.
$result = match ($status) {
    'pending' => 'Order is being processed',
    'shipped' => 'Order is on its way',
    default => 'Unknown status',
};
Real-world example An order status display function uses a match expression to cleanly convert a status code directly into a corresponding user friendly message, avoiding the verbose break statements and loose comparison pitfalls that the equivalent switch statement would have required.

Common follow-ups: What happens if a match expression does not have a matching condition and no default case is provided?;Can a single match arm handle multiple possible values?

Basics & Types;Constants & Superglobals

What is the nullsafe operator introduced in PHP 8, and how does it simplify safely accessing a chain of potentially null properties or methods?

Beginner
The nullsafe operator, written as a question mark followed by an arrow, lets you safely access a property or call a method on an object that might be null, automatically short circuiting and returning null for the entire chain the moment any link in that chain is null, rather than throwing an error, eliminating the need for a series of nested isset checks or explicit null comparisons that were previously required to safely navigate a chain of potentially missing related objects.
$city = $user?->address?->city;
// Returns null safely if user or address is null, instead of throwing an error
Real-world example A user profile display safely retrieves a user's city using the nullsafe operator, gracefully handling cases where a user has no associated address record at all, without needing several nested conditional checks to avoid an error.

Common follow-ups: How did developers handle this same scenario safely before PHP 8 introduced the nullsafe operator?;Can the nullsafe operator be used when calling a method rather than just accessing a property?

OOP;Functions & Scope

What are enums introduced in PHP 8.1, and how do backed enums differ from pure enums in terms of the values they can represent?

Intermediate
A pure enum defines a fixed set of named cases without any underlying scalar value associated with each case, while a backed enum additionally associates each case with a specific string or integer value, letting you convert between the enum case and its underlying value, which is especially useful when the enum's values need to be stored in a database or represented in an external API, unlike a pure enum which exists purely as a type safe in memory concept.
enum OrderStatus: string {
    case Pending = 'pending';
    case Shipped = 'shipped';
}
echo OrderStatus::Pending->value;
$status = OrderStatus::from('shipped');
Real-world example An order management system uses a backed enum for order status, storing the underlying string value directly in the database while working with the fully type safe enum case throughout the rest of the application code.

Common follow-ups: What is the difference between the from and tryFrom methods on a backed enum?;Can an enum implement an interface and have its own additional methods?

Constants & Superglobals;PDO & Databases

What are PHP attributes introduced in PHP 8, and how do they provide a structured, native alternative to the older convention of using docblock comments for metadata?

Intermediate
Attributes let you attach structured, machine readable metadata directly to a class, method, or property using a specific bracket based syntax, which can then be read and acted upon at runtime using PHP's reflection capabilities, providing a native, properly parsed alternative to the older convention of embedding similar metadata within docblock comments, which always required a separate, less reliable text parsing step to actually interpret.
#[Route('/users/{id}', methods: ['GET'])]
class UserController {
    public function show($id) {}
}
Real-world example A modern PHP framework uses attributes to define route mappings directly above controller methods, letting the framework's routing system reliably read this configuration through PHP's built in reflection capabilities rather than parsing potentially fragile docblock comments.

Common follow-ups: How do you read an attribute's data using PHP's reflection API at runtime?;What are common real world use cases for attributes in modern PHP frameworks?

OOP;Design Patterns in PHP

How do constructor property promotion, introduced in PHP 8, reduce boilerplate code when defining a class with several properties initialized directly through its constructor?

Intermediate
Constructor property promotion lets you declare and initialize a class property directly within the constructor's parameter list, simply by adding a visibility modifier before the parameter, eliminating the previously required boilerplate of separately declaring each property, adding a matching constructor parameter, and manually assigning that parameter's value to the corresponding property inside the constructor body.
class Point {
    public function __construct(
        public readonly float $x,
        public readonly float $y
    ) {}
}
Real-world example A developer refactors a data class that previously required a dozen lines of repetitive property declarations and constructor assignment code down to just a few concise lines using constructor property promotion, significantly improving readability.

Common follow-ups: Can constructor property promotion be combined with the readonly modifier?;Is there any functional difference between a promoted property and a traditionally declared one?

OOP;Type Declarations & Strict Types

How do union types and intersection types in PHP 8 provide more expressive and precise type declarations than were previously possible?

Advanced
Union types, introduced in PHP 8, let a parameter, property, or return type accept one of several specified types, such as accepting either an integer or a string, while intersection types, introduced in PHP 8.1, require a value to simultaneously satisfy multiple interfaces at once, both providing significantly more precise and expressive type declarations than were possible in earlier PHP versions, which previously often required falling back to the less precise generic mixed type or relying purely on docblock comments for this kind of nuanced type information.
function processId(int|string $id): void {
}

function save(Countable&Iterator $collection): void {
}
Real-world example A function accepting either a numeric database identifier or a string based slug uses a union type to precisely document both accepted possibilities, letting PHP itself enforce and validate this constraint rather than relying purely on a comment that could easily become outdated.

Common follow-ups: How do union types interact with strict_types mode regarding automatic type coercion?;What are practical real world use cases specifically for intersection types?

Type Declarations & Strict Types;OOP

How can PHP 8's readonly properties, enums, and first class callable syntax be combined together to build more robust, immutable, and expressive domain models compared to earlier PHP versions?

Advanced
Combining readonly properties for guaranteed immutability, backed enums for representing a fixed, type safe set of domain concepts like an order status, and first class callable syntax for cleanly referencing existing methods as callables, lets developers building domain models express business concepts with significantly stronger guarantees and less boilerplate than was achievable in earlier PHP versions, where similar intent often had to be enforced purely through convention and documentation rather than the language itself actively catching violations.
final class Order {
    public function __construct(
        public readonly string $id,
        public readonly OrderStatus $status,
    ) {}
}
$statuses = array_map(OrderStatus::from(...), $rawStatuses);
Real-world example A team modernizing a legacy PHP application redesigns its core Order domain model using readonly properties and a backed enum for status, immediately eliminating an entire category of bugs where an order's status or identifier could previously be accidentally mutated somewhere deep within the codebase.

Common follow-ups: How do these modern PHP 8 features specifically compare to similar immutability and type safety features in other programming languages?;What migration challenges arise when adopting these features in a large, existing legacy codebase?

OOP;Design Patterns in PHP