PHP 7.1: Major Features

PHP 7.1 makes typed PHP practical day-to-day: nullable types (?T), void returns, the iterable pseudo-type, visibility on class constants, list() with keys, multi-catch, and async-style quality-of-life improvements (e.g. Closure::fromCallable()). It also tightens runtime edges—most famously ArgumentCountError when user-defined functions are called with too few arguments—and changes subtle behavior around strings, DateTime, unserialize() options, and sorting stability. Plan migrations around: argument arity, session INI removals, and any code that treated strings like arrays with [].

Table of Contents


Nullable types (?T)

Parameters and return types may be ?Foo—accepting Foo or null. You still must return a value (or null) on all paths; bare return; is invalid unless the return type is void.

function findUser(?int $id): ?User {
    return $id === null ? null : User::load($id);
}

void return type

Functions that do not return a usable value can declare void. return; is allowed; return $value; is not.

iterable type

iterable accepts arrays or any object implementing Traversable—a single type for “foreach-able” inputs.

Class constant visibility

Constants support public / protected / private visibility like properties.

list() with keys & symmetric destructuring

list() can target specific keys (list(0 => $a, 1 => $b) = ... style patterns per manual), and the short [$a, $b] = $arr destructuring syntax arrives—use it to clarify tuple unpacking.

Multi-catch

try {
    // ...
} catch (FooException | BarException $e) {
    // shared handler
}

Notable additions

  • Closure::fromCallable() for wrapping callables with a real Closure instance.
  • void / ?Type interplay documented strictly by the engine.
  • pcntl_async_signals() and curl_multi_errno() / curl_share_errno() (see migration71 new features for the full list).

Practical recipes

Avoid too-few-argument calls

function save(User $user, bool $flush = false): void { /* ... */ }
// Always pass required args explicitly; optional params must truly be optional.

Nullable + early return

function label(?string $s): string {
    return $s ?? 'default';
}

Backward incompatible changes

User-defined arity

  • Calling a user-defined function with too few arguments now throws ArgumentCountError (previously: warning). Internal functions largely keep old behavior—audit wrappers that relied on warnings.

Session INI removed

  • session.entropy_file, session.entropy_length, session.hash_function, session.hash_bits_per_character are gone—modern session IDs no longer use that hashing pipeline (see RFC on session ID generation).

Arrays, references, sorting

  • Auto-vivified array elements via reference assignment may appear in a different order than PHP 7.0 (and align closer to PHP 5 behavior in common patterns—verify if you depended on 7.0 ordering).
  • Sorts may reorder equal-comparing elements differently—never rely on stability of ties.

Strings vs arrays

  • The empty [] append on strings ($s[] = 'x' with $s as string) and related “string as array” patterns are rejected—strings are not autovivified into arrays anymore. Assigning into numeric offsets on strings now follows byte-offset string semantics (see manual examples).

Serialization & time

  • unserialize($data, $options): allowed_classes must be bool or array—other types false + warning.
  • DateTime / DateTimeImmutable constructed from “now” include microseconds—naive equality of two “just created” instances often fails.

JSON, mbstring, TLS

  • With JSON_UNESCAPED_UNICODE, U+2028 / U+2029 are escaped.
  • mb_ereg() / mb_eregi() third arg is set to empty array when no match.
  • sslv2 stream removed from OpenSSL.

Lexical closures

  • use variables cannot reuse superglobal names, $this, or parameter names.

Wide “fatal → Error” sweep

Many extensions now throw Error instead of fatals for invalid internal states—see migration71 incompatible for the long per-extension list (DOM, Intl, mysqli, Session handlers, SimpleXML, SPL, Zip, …).

Deprecations

  • ext/mcrypt is deprecated (removed from core in PHP 7.2—plan OpenSSL/Sodium).
  • e modifier for mb_ereg_replace() / mb_eregi_replace() deprecated (eval-style replacement).

Other changes

  • Invalid numeric string arithmetic now emits warnings/notices where silent coercion happened before.
  • Octal escape overflows in strings warn.

Closing thoughts

Treat PHP 7.1 as “typed PHP v1”: nullable/void/iterable unlock safer APIs, but ArgumentCountError and string offset changes will surface latent bugs from PHP 5-era code. Fix arity and string handling before chasing 7.2’s count() warnings.