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


Likes(0)

Comment list count 0 Comments

No Comments