WHat's new in PHP 8.1
MergePHP December 2021
Hunter Skrasek
Thanks to release managers Joe Watkins, Ben Ramsey, and Patrick Allert
Also, 8.1.1RC1 dropped December 3rd, for folks who don't believe in .0 releases
What we'll cover
- Where to get it now
- What's new
- What's deprecated/removed
- How to find out more information
How do I get it?
- macOS: brew install php@8.1
- Ubuntu/Debian instructions (aka use Ondrej's repo)
- Red Hat-based: use Remi's repo
- Inside Docker: e.g. php:8.1.0-fpm-alpine3.15
- Windows builds can be downloaded here
- Source code to build yourself is on php.net
enum Status // singleton; Status::Active === Status::Active { case Active; case Expired; case Cancelled; case Pending; public function isActive(): bool {} // can be static // Look ma, no constants! }
Enums - Backed
enum Status: string // can be int { // can implement JsonSerializeable case Active = 'active'; case Expired = 'expired'; case Cancelled = 'cancelled'; case Pending = 'pending'; } // can't be used as array keys...for now json_serialize(Status::Active); // 'active' Status::Active->value; // 'active' Status::from('active'); // Status::Active Status::tryFrom('activv'); // null; would throw on ::from
Enums - Yes, interfaces work with them
interface HasColor { public function getColor(): Color; } enum Status implements HasColor { // cases go brr public function getColor(): Color {} // Can also include traits, but no properties }
class ValueObject { public function __construct( public readonly string $value ) {} } $foo = new ValueObject('foo'); echo $foo->value; // foo $foo->value = 'bar'; // throws
$foo = $this->foo(...); // instead of [$this, 'foo']; $fn = strlen(...); // instead of Closure::fromCallable('strlen');
New in initializers (allows nested atTributes)
Old: class Service { public function __construct(protected Logger = null) { $this->logger ??= new Logger(); } } New: class Service { public function __construct( protected Logger = new Logger() ) {} }
function process( HasId&HasName $item ): Result&ArrayAccess { // do stuff }
You could extend interfaces and then implement the extended interfaces, but this lets you get the same effect without touching the implementation classes at all.
function throwThings(): never { throw new \RuntimeException('things'); } // Different from void return type since it never returns
This helps with static analysis, for detecting dead code. The "never" type also applies to functions that die or trigger errors 100% of the time.
class Base { public const NAME = 'Base'; final public const STATUS_ACTIVE = 'active'; // lets your constants actually be constant } class Extended extends Base { public const NAME = 'Extended'; // works public const STATUS_ACTIVE = 'passive'; // fails }
016 === 16; // false 016 === 14; // true 0o16 === 14; // true 0x16 === 22; // true
$fiber = new Fiber(function (): void {
$valueAfterResuming = Fiber::suspend('after suspending');
// …
});
$valueAfterSuspending = $fiber->start();
$fiber->resume('after resuming');
You'll use these in an event loop, e.g. React/AMPHP. This is not parallel processing
$array1 = ["a" => 1]; $array2 = ["b" => 2]; $array = ["a" => 0, ...$array1, ...$array2]; var_dump($array); // ["a" => 1, "b" => 2]
This follows array_merge semantics
Performance Improvements
- JIT for Arm64 (new Macs, AWS Graviton2)
- Some other JIT improvements
- Inheritence cache (vs. re-linking classes in each request)
- Fast class name resolution
- Misc. performance improvements
- Timelib + ext/date
- SPL file system iterator
- Serialize/deserialize
- get_declared_classes(), explode(), strtr(), strnatcmp(), dechex()
- 23% Symfony demo speedup, 3.5% WordPress speedup
...and more!
Deprecation + BC Break Time
Type breaks
- Internal functions now have return types
- If you're extending an internal class (e.g. PDO) you need to add these types
- Can get around this for now by adding the #[ReturnTypeWillChange] attr
- Deprecated: Passing null to non-nullable internal functions is now deprecated
- Deprecated: Old-style serializeable interface (better way as of PHP 7.4)
- Deprecated: Casting floats to integers whose values aren't actually equal
Type breaks 2: Resources that are now objects
- file_info(): finfo
- IMAP resources -> IMAP\Connection
- FTP resources -> FTP\Connection
- GD font identifiers -> GdFont
- LDAP resources -> LDAP\{Connection, Result, ResultEntry}
- Postgres resources -> PgSql\{Connection, Result, Lob}
- Pspell -> Pspell\{Dictionary, Config}
Other database changes
- MySQLi now throws exceptions by default
- Integers from PDO actually return as ints rather than stringy numbers
- Here's what it takes to be PHP 7.2->8.1 compatible (vs. 8.1+ only) in Aura.Sql
Other functionality changes
- ' now gets encoded as ' in escaping functions
-
$GLOBALS is now less flexible
- Can't write to it as a whole
- Reading from it as a whole is read-only
- Reading from/writing to array values inside $GLOBALS still works
Further Reading
Thanks! Questions?
What's New in PHP 8.1 - MergePHP December 2021
By Ian Littman
What's New in PHP 8.1 - MergePHP December 2021
- 682