PHP 8: Modern PHP Development · Modern PHP Syntax & Types
The PHP 8 Type System
Scalar, union, nullable, intersection, mixed, never and DNF types.
PHP 8 lets you declare types for parameters, return values and properties. Beyond scalars (int, float, string, bool) and classes you get union types (int|string, 8.0), mixed (8.0), static returns (8.0), never for functions that always throw or exit (8.1), intersection types (Countable&Iterator, 8.1), standalone null, false and true types (8.2) and DNF types like (A&B)|null (8.2).
Types document intent, catch bugs early, and let static analyzers (PHPStan, Psalm) and IDEs reason about your code.
<?php
declare(strict_types=1);
function parseId(int|string $id): int
{
return is_int($id) ? $id : (int) $id;
}
/** @param array<int, User> $users */
function findUser(array $users, int $id): ?User // nullable: User|null
{
return $users[$id] ?? null;
}
function fail(string $message): never // never returns normally
{
throw new DomainException($message);
}
function process((Countable&Traversable)|null $items): void { /* DNF type */ }
Common pitfalls
- Using
mixedeverywhere — it disables most benefits of typing. - Confusing
?T(nullable) with an optional parameter;?int $xstill requires an argument unless it has a default. - Assuming types are checked inside arrays —
arraysays nothing about element types (use PHPDoc generics likelist<User>for analyzers).
Key points
- Union, intersection and DNF types make signatures precise
nevermarks functions that always throw/exit- Use PHPDoc generics for array element types
Further reading: PHP manual: type declarations
Practice questions
What is the difference between ?string and string|null?
Answer
None — ?string is shorthand for string|null. The ? shorthand can't be combined with other union members, so int|string|null must be written in full.
When would you use the never return type?
Answer
For functions that never return normally: they always throw an exception or call exit(). It helps static analysis understand that code after the call is unreachable, e.g. a fail() or redirect() helper.
Open in the app to mark lessons complete, take notes and track your progress.