Why Upgrade to PHP 8?
PHP 8 (Nov 2020) and its 8.1, 8.2, 8.3 successors added the language features PHP developers had been asking for for a decade. Plus the JIT, performance gains, and better type safety throughout.
Named Arguments (PHP 8.0)
<?php
// Skip middle defaults
htmlspecialchars($input, double_encode: false);
// Self-documenting calls
$user = createUser(
name: "Ruban",
email: "x@y.com",
role: "admin",
active: true,
);
match Expression (PHP 8.0)
<?php
$label = match ($status) {
1, 2 => "Active",
3 => "Pending",
4 => "Banned",
default => "Unknown",
};
Returns a value, uses strict comparison (===), throws on no match unless default. Replaces 90% of switch statements.
Nullsafe Operator ?-> (PHP 8.0)
<?php
// Old way
$country = null;
if ($user !== null && $user->address !== null) {
$country = $user->address->country;
}
// PHP 8.0+
$country = $user?->address?->country;
Union & Intersection Types
<?php
// Union (8.0) - accept multiple types
function format(int|string $value): string {
return (string) $value;
}
// Intersection (8.1) - must satisfy MULTIPLE interfaces
function process(Iterator&Countable $data): void { /* ... */ }
// Disjunctive Normal Form (8.2) - union of intersections
function handle((Iterator&Countable) | array $input): void { /* ... */ }
// New built-in types: false, true, null as standalone (8.2)
function example(): false|string { return "ok"; }
Constructor Property Promotion (PHP 8.0)
<?php
// Before
class User {
private string $name;
public function __construct(string $name) {
$this->name = $name;
}
}
// After
class User {
public function __construct(private string $name) {}
}
Attributes (PHP 8.0)
First-class metadata replacement for docblock annotations:
<?php
#[Attribute]
class Route {
public function __construct(public string $path) {}
}
class UserController {
#[Route("/users")]
public function index() { /* ... */ }
#[Route("/users/{id}")]
public function show(int $id) { /* ... */ }
}
// Reflect at runtime
$ref = new ReflectionMethod(UserController::class, "show");
foreach ($ref->getAttributes(Route::class) as $attr) {
$route = $attr->newInstance();
echo $route->path; // "/users/{id}"
}
Enums (PHP 8.1)
<?php
enum Status: string {
case Pending = "pending";
case Active = "active";
case Banned = "banned";
public function color(): string {
return match($this) {
self::Pending => "yellow",
self::Active => "green",
self::Banned => "red",
};
}
}
$s = Status::Active;
echo $s->value; // "active"
echo $s->color(); // "green"
// From a stored value
$s = Status::from("active"); // Status::Active
$s = Status::tryFrom("xxx"); // null - no exception
readonly Properties & Classes
<?php
// Property-level readonly (8.1)
class Money {
public function __construct(
public readonly int $cents,
public readonly string $currency,
) {}
}
$m = new Money(1999, "USD");
// $m->cents = 0; // ERROR - readonly
// Class-level readonly (8.2) - all properties readonly
readonly class Point {
public function __construct(
public float $x,
public float $y,
) {}
}
First-Class Callable Syntax (PHP 8.1)
<?php
// Before
$upper = array_map("strtoupper", $words);
// PHP 8.1 - IDE-aware, refactor-safe
$upper = array_map(strtoupper(...), $words);
// Works with methods too
$saver = $repo->save(...);
$saver($entity);
Fibers (PHP 8.1)
Primitives for cooperative concurrency. You probably won't write fibers directly but they power async frameworks:
<?php
$fiber = new Fiber(function (): void {
$value = Fiber::suspend("hello");
echo "Resumed with: $value\n";
});
$value = $fiber->start(); // "hello"
$fiber->resume("world"); // "Resumed with: world"
Misc 8.2 / 8.3 Wins
- Typed class constants (8.3):
const string VERSION = "1.0"; - json_validate() (8.3): check JSON validity without decoding overhead
- #[Override] attribute (8.3): static check that a method really overrides a parent
- Readonly classes (8.2): shorthand fully-immutable objects
- Standalone
true/false/nulltypes (8.2) - Constants in traits (8.2):
trait T { const X = 1; } - Random extension (8.2):
Random\Randomizerwith pluggable engines - str_contains / str_starts_with / str_ends_with (8.0): the obvious string helpers