Array functions, string methods, and new features.
match expression$label = match($code) { 200 => 'OK', 404 => 'Not Found', default => 'Unknown' };Named argumentsarray_slice(array: $arr, offset: 2, length: 5, preserve_keys: true);Nullsafe operator (?->)$city = $user?->getAddress()?->getCity()?->getName();Union types (int|string)function process(int|string $id): User|null { ... }Fibers (8.1)$fiber = new Fiber(function() { $val = Fiber::suspend('first'); echo $val; }); $fiber->start(); $fiber->resume('second');Enums (8.1)enum Status: string { case Active = 'active'; case Pending = 'pending'; public function label(): string { return ucfirst($this->value); } }Readonly properties (8.1)class User { public function __construct(public readonly int $id, public readonly string $email) {} }First class callables (8.1)$fn = strlen(...); $sorted = usort($arr, strcmp(...));array_map / array_filter$names = array_map(fn($u) => $u->name, $users); $active = array_filter($users, fn($u) => $u->active);array_reduce$total = array_reduce($items, fn($carry, $item) => $carry + $item->price, 0);array_column$emails = array_column($users, 'email'); $byId = array_column($users, null, 'id');usort / uasort / uksortusort($posts, fn($a, $b) => $b->views <=> $a->views);array_unique / array_diff$new = array_diff($all, $existing); $common = array_intersect($a, $b);str_contains / str_starts_withif (str_starts_with($url, 'https') && str_contains($body, 'error')) { ... }sprintf / number_formatsprintf("%.2f", $price); number_format(1234567.89, 2, '.', ',')preg_match / preg_replace / preg_splitpreg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $date, $m); $m[1]; $m[2]; $m[3];Constructor promotionclass Product { public function __construct(private string $name, private float $price) {} }Interface / Abstract classinterface Cacheable { public function getCacheKey(): string; public function ttl(): int; }Traitstrait Timestampable { public function touch(): void { $this->updated_at = new DateTime(); } }Late static binding (static::)class Base { public static function create(): static { return new static(); } }__invoke / __toStringclass Multiplier { public function __invoke(int $n): int { return $n * $this->factor; } }Repository patterninterface UserRepo { public function findById(int $id): ?User; public function save(User $u): void; }Dependency Injectionclass OrderService { public function __construct(private OrderRepo $orders, private Mailer $mail) {} }password_hash / verify$hash = password_hash($pass, PASSWORD_ARGON2ID); password_verify($input, $hash);htmlspecialcharsecho htmlspecialchars($user_input, ENT_QUOTES | ENT_HTML5, 'UTF-8');PDO prepared statements$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?"); $stmt->execute([$email]);csrf_token pattern$_SESSION['csrf'] = bin2hex(random_bytes(32)); // verify: hash_equals($session_token, $post_token)random_bytes / random_int$token = bin2hex(random_bytes(32)); $code = random_int(100000, 999999);hash_hmac$sig = hash_hmac('sha256', $payload, $_ENV['SECRET_KEY']);filter_var validationif (!filter_var($email, FILTER_VALIDATE_EMAIL)) { throw new \InvalidArgumentException('Bad email'); }environment variables$key = $_ENV['DB_PASSWORD'] ?? throw new \RuntimeException('Missing DB_PASSWORD');set_exception_handlerset_exception_handler(fn($e) => logAndRespond($e));Throwable interfacetry { ... } catch (\Throwable $e) { logger()->critical($e->getMessage()); }Generator::send()$gen = logger(); $gen->current(); $gen->send("message to log");file_put_contents / file_get_contentsfile_put_contents('app.log', $msg . PHP_EOL, FILE_APPEND | LOCK_EX);SplFileObject / SplQueue$csv = new SplFileObject('data.csv'); $csv->setFlags(SplFileObject::READ_CSV); foreach($csv as $row) { ... }DateTime / DateTimeImmutable$expires = (new DateTimeImmutable())->add(new DateInterval('P30D'));