PHP 8.1 has landed! ๐ Here’s what’s new.
We are pleased to announce that PHP 8.1 support has been tested and added to all WordFleet servers. You can switch individual sites over to it whenever you are ready.
As PHP 8.1 is hot off the press, we’re keeping the default version for new sites pegged at 8.0. We’ll update the default to 8.1 in the coming weeks, but you can switch new and existing sites to 8.1 at any time. Check out the migration notes below before you do.
Note that most of the content below has been adapted from the official PHP announcement. We are listing most new features here for convenience. Please do read the original post for full details. All credit here goes to the PHP devs โค๏ธ
PHP 8.1 key features include:
๐ Performance Boosts
PHP 8.1 further improves upon the performance gains from its predecessor. According to the official PHP 8.1 announcement, WordPress sites can expect to see a general performance increase of 3.5% relative to PHP 8.0. The Symphony Demo app saw an impressive speed increase of 23%.
๐งฎ Enumerations (enums)
Enums are a common feature in most other languages. They allow developers to mix type safety with numeric constants. This ensures that you can’t put invalid values where a specific enum type belongs.
class PostStatus
{
const DRAFT = 1;
const PUBLISHED = 2;
const ARCHIVED = 3;
}
function doSomethingWithStatus(int $status) { ... }
enum Status
{
case Draft;
case Published;
case Archived;
}
function doSomethingWithStatus(Status status) { ... }
๐ซ Read-only Properties
Prior to PHP 8.1, in order to get read-only properties, you would be required to make a property private and expose its value via a getter function. Now, you can use the readonly
modifier to ensure that the property is available for direct access but not mutable once assigned.
class BlogPost
{
private Status $status;
public function __construct(Status $status)
{
$this->status = $status;
}
public function getStatus(): Status
{
return $this->status;
}
}
class BlogPost
{
public readonly Status $status;
public function __construct(Status $status)
{
$this->status = $status;
}
}
โ๏ธ First-class Callable Syntax
You can now reference any function, including with its $this
context, by placing an ellipsis between the function call paranthesis ()
.
// A reference to $this->getName()
$getThisName = [$this, 'getName'];
$getThisName();
// A reference to the function strlen
$strlen = Closure::fromCallable('strlen');
$str = 'foo';
echo $strlen($str); // 3
$getThisName = $this->getName(...);
$getThisName();
$strlen = strlen(...);
$str = 'foo';
echo $strlen($str); // 3
๐ in initializers
You can now use the new
keyword to initialize:
- Default parameter values
- Static variables
- Global constants
- Attribute arguments
class Service
{
private Logger $logger;
public function __construct(
?Logger $logger = null,
) {
$this->logger = $logger ?? new NullLogger();
}
}
class Service
{
private Logger $logger;
public function __construct(
Logger $logger = new NullLogger(),
) {
$this->logger = $logger;
}
}
This also makes it possible to use nested attributes.
class User
{
/**
* @Assert\All({
* @Assert\NotNull,
* @Assert\Length(min=5)
* })
*/
public string $name = '';
}
class User
{
#[\Assert\All(
new \Assert\NotNull,
new \Assert\Length(min: 6))
]
public string $name = '';
}
๐ฆ Pure Intersection Types
Intersection types are useful when a particular input value must satisfy multiple type constraints simultaneously.
The announcement notes that it is not currently possible to mix intersection and union types together such as A&B|C
.
function count_and_iterate(Iterator $value) {
if (!($value instanceof Countable)) {
throw new TypeError('value must be Countable');
}
foreach ($value as $val) {
echo $val;
}
count($value);
}
function count_and_iterate(Iterator&Countable $value) {
foreach ($value as $val) {
echo $val;
}
count($value);
}
๐ Static analyzers rejoice! A new return type: never
You can now specify never
as the return type of a function to indicate that it halts execution of the program, indicating the code below it is effectively dead.
function redirect(string $uri) {
header('Location: ' . $uri);
exit();
}
function redirectToLoginPage() {
redirect('/login');
// This code is dead, but IDEs may not warn you as such.
echo 'Hello';
}
function redirect(string $uri): never {
header('Location: ' . $uri);
exit();
}
function redirectToLoginPage(): never {
redirect('/login');
// This code is easily marked as dead by most static analyzers.
echo 'Hello';
}
๐ Final class constraints
You can now ensure that class constants are final, guaranteeing that attempts to overwrite them in child classes cause a fatal error.
class Birb
{
public const CONSTANT = "Arthur";
}
class Duck extends Birb
{
// No error. The constant has been replaced.
public const CONSTANT = "Diana";
}
class Birb
{
final public const CONSTANT = "Arthur";
}
class Duck extends Birb
{
// A fatal error. What have you done?
public const CONSTANT = "Diana";
}
๐ Explicit octal numeral notation
Not very exciting, but much less confusing. You may prefix octal notation with 0o
. No 0w0
notation yet though, sadly.
016 === 16; // false because `016` is octal for `14` and it's confusing
016 === 14; // true
0o16 === 16; // false โ not confusing with explicit notation
0o16 === 14; // true
๐ฆ Array unpacking support for string-keyed arrays
PHP used to support unpacking inside arrays, but only if the arrays had integer keys. PHP 8.1 adds support to unpack arrays with string keys too.
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];
$result = array_merge(['a' => 0], $arrayA, $arrayB);
// ['a' => 1, 'b' => 2]
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];
$result = ['a' => 0, ...$arrayA, ...$arrayB];
// ['a' => 1, 'b' => 2]
๐งต Fibers
Oh baby. The exciting stuff for framework developers like ourselves. Fibers are the building blocks for implementing lightweight cooperative concurrency.
Fibers themselves don’t function like goroutines in programming languages like Go. You will need a proper event loop to run them, but they allow blocking and non-blocking implementations to share the same API.
This effectively eliminates:
- Alternate versions of functions suffixed with
Async
orSync
. - The usual boilerplate around promises.
Most developers won’t use fibers directly in their day to day. However, this addition will make developing concurrent applications much more fluent as popular frameworks and libraries begin to use them.
๐ Want to read more?
There’s more information available, including new deprecations and backwards compatibility breaks, in the official PHP 8.1 announcement post.
There are some detailed notes on deprecations and backwards compatibility breakages, so definitely give it a read. Or don’t. I’m just a blog, not a cop.
๐ Migration Notes
For existing sites, we highly recommend that you test it on a dev or staging site first. This will ensure that your site functions correctly with the new update, especially if you have an older theme or a lot of plugins.
You’re probably fine if you’re already running smoothly on PHP 8.0. Regardless, we do recommend testing as there have been a few deprecations and backwards compatibility breakages in this update.
๐ Conclusion
PHP 8.1 is an exciting update to the language, and we’re pleased to announce our support of it fleet wide. We hope you’ll test it out soon.
WordFleet offers premium managed WordPress hosting with no site or visitor limits. Prices start at $12 / server per month.