PHP 8.1 has been released on November 25, 2021. In this article, we will introduce all the features, performance improvements, changes, and deprecations one by one.
New features
Like every version, PHP 8.1 adds some nice new features. More and more new features will be updated every year.
Enumerate RFC
Enumeration will be supported in PHP 8.1! If you are not sure where enumeration can be used, you can read this document.
The addition of enumerations will be a big step forward for PHP, so I am looking forward to the enumerations in PHP 8.1. You can view the following code example to have a quick preview of the enumeration:
enum Status {
case Pending;
case Active;
case Archived;
}
Here is how they are used:
class Post
{
public function __construct(
private Status $status = Status::Pending;
) {}
public function setStatus(Status $status): void
{
//…
}
}
$post->setStatus(Status::Active);
You can find an in-depth analysis of how to use enums in this article.
Fibers RFC
Fibers-also called "green threads"-are low-level mechanisms for managing parallelism. You may not use it directly in your application, but frameworks like Amphp and ReactPHP will use them heavily.
Here is a simple example using fibers:
$fiber = new Fiber(function (): void {
$valueAfterResuming = Fiber::suspend('after suspending');
//…
});
$valueAfterSuspending = $fiber->start();
$fiber->resume('after resuming');
If you want to read more information about fibers, what they can and cannot do, you can read [this article](https://stitcher.io/blog/fibers-with-a-grain-of- salt).
Performance improvement PR
Dmitry Stogov made some improvements to opcache, which he called "inheritance cache". This new feature allows two classes to be connected in the cache, just like the preloading of the two classes in PHP 7.4.
Thanks to this new feature, Dmitry said it will improve performance by 5% to 8%, which is a nice little detail in PHP 8.1.
Associative array unpacking RFC
The unpacking operation of arrays has been supported in PHP 7.4, but it is only easy to use in numeric arrays. The reason that associative array unpacking was not supported before was because there was no unification on the issue of merging duplicate array keys. The RFC uses a rule similar to array_merge
to solve this problem.
$array1 = ["a" => 1];
$array2 = ["b" => 2];
$array = ["a" => 0, ...$array1, ...$array2];
var_dump($array); // ["a" => 1, "b" => 2]
Use new
to initialize RFC
This RFC allows you to use the keyword new
as the default parameter in the function definition, and it can also be used in places such as attribute parameters.
class MyController {
public function __construct(
private Logger $logger = new NullLogger(),
) {}
}
You can read all about this feature in this feature article.
Read-only attribute RFC
Class attributes can be marked as read-only, which means they can only be written once.
class PostData {
public function __construct(
public readonly string $title,
public readonly DateTimeImmutable $date,
) {}
}
After initializing the read-only property, attempting to change the property will result in an error:
$post = new Post('Title', /*… */);
$post->title ='Other';
Error: Cannot modify readonly property Post::$title
If you want to learn more about read-only properties, you can read my follow-up article.
Do you want to learn more about PHP 8.1? You can take a look at Road to PHP 8.1. For the next ten days, you will receive an email every day that contains the new and existing features of PHP 8.1; after that, you will be automatically unsubscribed, so there is no need to worry about spam. Subscribe now!
The best callable syntax RFC
You can now create a closure by calling a method and passing ...
to it.
function foo(int $a, int $b) {/*… */}
$foo = foo(...);
$foo(a: 1, b: 2);
Pure cross type in RFC
You have already learned about Union Types in PHP 8.0, the intersection type is a similar function. If the requirement of the joint type is that the input type is in a given type, then the requirement of the cross type is that the input type is all specified types. The crossover type is particularly useful when dealing with a large number of interfaces:
function generateSlug(HasTitle&HasId $post) {
return strtolower($post->getTitle()). $post->getId();
}
If you like this code style, you need to create a new interface Sluggable
and implement it in $post
. The cross type solves this additional overhead.
New type never
RFC
The never
type can be used to indicate that the entire program terminates in a function. It can be achieved by throwing an exception, calling exit
, or other similar functions.
function dd(mixed $input): never
{
// output content
exit;
}
The difference between never
and void
is that void
means that the program is still running. This seems to be a novel feature, but in fact it is a very useful feature for static analysis.
New function array_is_list
RFC
You may occasionally need to deal with a problem like this: determine whether the keys of the array are arranged in numerical order starting from index 0. For example, json_encode
needs to decide whether to convert json into an array or an object.
PHP 8.1 added a built-in function to determine whether an array is a list with these semantics:
$list = ["a", "b", "c"];
array_is_list($list); // true
$notAList = [1 => "a", 2 => "b", 3 => "c"];
array_is_list($notAList); // false
$alsoNotAList = ["a" => "a", "b" => "b", "c" => "c"];
array_is_list($alsoNotAList); // false
Final class constant RFC
Class constants in PHP can be overwritten during inheritance:
class Foo
{
public const X = "foo";
}
class Bar extends Foo
{
public const X = "bar";
}
Starting with PHP 8.1, you can mark such constants as final
to prevent this:
class Foo
{
final public const X = "foo";
}
class Bar extends Foo
{
public const X = "bar";
Fatal error: Bar::X cannot override final constant Foo::X
}
New Sync
function RFC
PHP 8.1 adds the fsync
function and the fdatync
function to force the file to be changed to the disk synchronously, and to ensure that the operating system write buffer is flushed before returning.
$file = fopen("sample.txt", "w");
fwrite($file, "some content");
if (fsync($file)) {
echo "File has been successfully saved to disk";
}
fclose($file);
Because disk synchronization is a file system operation, the fsync
function will only work on ordinary file streams. Attempting to synchronize a non-file stream will issue a warning.
Explicit octal integer literal representation RFC
You can now use 0o
and 0O
to represent octal numbers. The previous notation with 0
as the prefix is still valid.
016 === 0o16; // true
016 === 0O16; // true
Breakthrough changes
Although PHP 8.1 is a minor version, there may be some breakthrough changes in technology, and of course there are some objections. Let's discuss them one by one.
Internal method return type RFC
When upgrading to PHP 8.1, you may see this deprecation notice:
Return type should either be compatible with IteratorAggregate::getIterator(): Traversable,
or the #[ReturnTypeWillChange] attribute should be used to temporarily suppress the notice
You may have noticed that this error message will be in the use of phpunit/phpunit
, symfony/finder
and other popular open source packages. Actually, it is because the internal function starts to use the correct return type. If you want to inherit a class from the standard library (such as IteratorAggregate
), you also need to add a return type.
The fix is simple: if there is an error in the third-party software package, please update the code of the software package (most of which have been fixed in the latest version). If there are errors in the code, you can add the ReturnTypeWillChange
attribute to suppress these errors before PHP 9.0. Here is an example of a class extending DateTime
:
class MyDateTime extends DateTime
{
/**
* @return DateTime|false
*/
#[ReturnTypeWillChange]
public function modify(string $modifier)
{
return false;
}
}
Or you can add the return type:
class MyDateTime extends DateTime
{
public function modify(string $modifier): DateTime|false
{
return false;
}
}
Restrict the use of $GLOBALS
RFC
A small change to the way $GLOBALS
is used will have a major impact on the performance of all array operations. Nikita explained the problem and solution well in RFC. This change means that $GLOBALS
will not do anything in some edge cases. $GLOBALS no longer supports global writing. The following actions will report an error.
$GLOBALS = [];
$GLOBALS += [];
$GLOBALS =& $x;
$x =& $GLOBALS;
unset($GLOBALS);
Calling $GLOBALS
by reference will cause a runtime error
by_ref($GLOBALS);
Nikita analyzed the top 2000 packages on Packagist and found only 23 cases that would be affected by this change. We can conclude that the impact of this technological breakthrough change will be minimal, which is why the internal decision to add them to PHP 8.1. Remember, most developers will benefit from it, and the positive impact on our code will be everywhere.
Resource to object migration
These changes are part of a long-term vision to transform all resources into dedicated objects. You can learn more about it here.
Fileinfo function with finfo
object
Functions such as finfo_file
and finfo_open
are used to accept and return resources. Starting from PH P8.1, they can use all finfo
objects.
IMAP function with IMAPConnection
object
Just like the changes in fileinfo, IMAP functions like imap_body
and imap_open
no longer use resources.
It is not recommended to pass null to non-nullable parameters RFC in internal functions
The change is simple: internal functions can currently accept null
for non-null parameters, and this RFC opposes this behavior. For example, this is now possible:
str_contains("string", null);
In PHP 8.1, such errors will throw a deprecation warning, and in PHP 9, they will become type errors.
Automatically change from false
to non-false (Autovivification) RFC
Autovivification is a self-made word in perl, but it has applications in many languages. Refer to [Perl's autovivification feature](https://www.cnblogs.com/f-ck-need-u/p/9718238.html#perl%E7%9A%84autovivification%E7%89%B9%E6%80% A7), WikipediaAutovivification (Translator's Note)
From RFC:
PHP inherently supports autovivification (automatically create an array from false values). This feature is very useful, especially when the value is not defined. And it has been used in many PHP projects. However, it is strange that it actually allows an array to be created from a false and a null.
You can read the details on the RFC page. In short, this behavior is not recommended:
$array = false;
$array[] = 2;
Automatic conversion of false to array is deprecated
Other minor changes
For each release, there will be some very small changes in the language. All of these are listed in GitHub's Upgrade Guide and [Deprecated RFC](https://wiki.php.net /rfc/deprecations_php_8_1), if you want to know every little detail, you must check it out.
Here are some of the most important changes:
-MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH
maximum length no longer has an effect
-MYSQLI_STORE_RESULT_COPY_DATA
is no longer valid
-PDO::ATTR_STRINGIFY_FETCHES Boolean values can now also be used
-When using simulated prepared statements, integers and floating point numbers in the result set of PDO MySQL and Sqlite will be returned using native PHP types instead of strings
-Functions like htmlspecialchars
and htmlentities
are also converted to '
by default; incorrectly formatted utf-8 will also be replaced by Unicode characters instead of generating an empty string
-hash
, hash_file
and hash _ init
will add an extra parameter $options
, its default value is []
, which will not affect existing code
-New support for MurmurHash3
and xxHash
Post comment 取消回复