PHP 8 New features & comparison with older versions.
Tags: php, php8, wordpress
Published: 2020-12-24 07:40:55

PHP 8.0 is a major update of the PHP language.
It contains many new features and optimizations including named arguments, union types, attributes, constructor property promotion, match expression, nullsafe operator, JIT, and improvements in the type system, error handling, and consistency...

## Table of contents
===
1. JIT Compiler.
2. PHP 8 New Features.
3. PHP 8 impact & compatibility (with Wordpress).
4. Deprecated functions.

### 1. The JIT (just-in-time) compiler
===
When PHP code is run, it's usually done by compiling & executed in a virtual machine. JIT will change this by compiling the code into x86 machine code and then running that code directly on the CPU. 
For applications that rely heavily on mathematical functions, this should improve performance.

It's the most important new feature updates in PHP 8, JIT is not enabled by default. However JIT doesn't make that much of a difference on web applications.

Example about JIT performance demonstrated:

{% youtube dWH65pmnsrI %}

Ref Source: [PHP 8 - New Features, Improvements and Potential Problems with WordPress](https://raidboxes.io/en/blog/webdesign-development/php-8/)

### 2. PHP 8 New features
===
Thanks to:
{% link https://dev.to/sesha/what-s-new-in-php-8-2ono %}

#### The nullsafe operator [RFC](https://wiki.php.net/rfc/nullsafe_operator)
Instead of writing classic !== null you can use the “?” operator to write just 1 line of code, the application application becomes pretty clear: 

Before: 
```php
$country =  null;

if ($session !== null) {
  $user = $session->user;

  if ($user !== null) {
    $address = $user->getAddress();
 
    if ($address !== null) {
      $country = $address->country;
    }
  }
}
```
After:
```php
$country = $session?->user?->getAddress()?->country;
```
#### Constructor property promotion
Instead of specifying class properties and a constructor for them, PHP can now combine them into one.

```php
// In php 7.x
class Point {
    protected float $x;
    protected float $y;
    protected float $z;
 
    public function __construct(
        float $x = 0.0,
        float $y = 0.0,
        float $z = 0.0,
    ) {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}

// In PHP 8
class Point {
    public function __construct(
        protected float $x = 0.0,
        protected float $y = 0.0,
        protected float $z = 0.0,
    ) {}
}
```

#### Union Types 2.0 [RFC](https://wiki.php.net/rfc/union_types_v2#php_rfcunion_types_20)
PHP is a dynamically typed structure, So union types are very useful in a lot of places. Union types are a collection of two or more types which indicate that either one of those can be used.

```php
// In PHP 7.4
class Number {
    private $number;

    public function setNumber($number) {
        $this->number = $number;
    }
}

// In PHP 8
class Number {
    private int|float $number;
 
    public function setNumber(int|float $number): void {
        $this->number = $number;
    }
}
```

#### Mixed Type [RFC](https://wiki.php.net/rfc/mixed_type_v2)
[Reference link](https://stitcher.io/blog/new-in-php-8)

Mixed type is a good addition to php8 type system. It is equivalent to one of these types.

```php
  array|bool|callable|int|float|null|object|resource|string
```
Here is an example from the RFC documentation of how this is used:
```php
public function foo(mixed $value) {}
```
Also note that since mixed already includes null, it's not allowed to make it nullable. The following will trigger an error:

```php
// Fatal error: Mixed types cannot be nullable, null is already part of the mixed type.
function bar(): ?mixed {}
```

### Match Expression [RFC](https://wiki.php.net/rfc/match_expression_v2)
Does match expression replace the switch?. The match can return values, doesn't require lengthy statements like a switch. It uses strict type comparison

```php
//The switch statement loosely compares (==) the given value to the case values. This can lead to some very surprising results.
switch ('100') {
  case 100:
    $price = "Oh no!";
    break;
  case '100':
    $price = "This is what I expected";
    break;
}
echo $price;
///> Oh no!

//The match expression uses strict comparison (===) instead. The comparison is strict regardless of strict_types.
echo match ('100') {
  100 => "Oh no!",
  '100' => "This is what I expected",
};
```
#### Named Arguments [RFC](https://wiki.php.net/rfc/named_params)
Named arguments give you more flexibility when calling functions. Previously, you had to call a function and pass each argument in the order in which the function specified. 

```php
class ExampleClass {

  public function __construct(
      private string $title, 
      private string|null $description, 
      private string $type ) {

  }
}

// In  PHP 7.x
$my_class = new Log (
  'New Support request',
  '',
  'support',
);

// In PHP 8
$my_class = new ExampleClass (
  title : 'New Support request',
  description : 'You received a new support ...',
  type: 'support',
);

// even you can write something like these
$my_class = new ExampleClass (
  title : 'New Support request',
  type: 'support',
);
```

#### Attributes
Instead of PHPDoc annotations, you can now use structured metadata with PHP's native syntax.
```php
// PHP 7
{
    /**
     * @Route("/api/posts/{id}", methods={"GET"})
     */
    public function get($id) { /* ... */ }
}

// PHP 8
class PostsController
{
    #[Route("/api/posts/{id}", methods: ["GET"])]
    public function get($id) { /* ... */ }
}
```

#### PHP New Functions & Classes
[New Classes, Interfaces, and Functions](https://www.php.net/releases/8.0/en.php)

- Attributes v2 [RFC](https://wiki.php.net/rfc/attributes_v2).
- Weak Maps [RFC](https://wiki.php.net/rfc/weak_maps).
- Throw Expression [RFC](https://wiki.php.net/rfc/throw_expression).
- Trailing Comma in Parameter List.
```php
class Comment {
  public function __construct(
   string $titla,
   string $description,
   int $status, // trailing comma
 ) {
   // do something
 }
}
```
- Inheritance with private methods [RFC](https://wiki.php.net/rfc/inheritance_private_methods).
- Arrays Starting With a Negative Index.
```php
$book = array_fill(-4, 6, 'title');
var_dump($book);
//output 
array(6) {
  [-4]=>
  string(5) "title"
  [-3]=>
  string(5) "title"
  [-2]=>
  string(5) "title"
  [-1]=>
  string(5) "title"
  [0]=>
  string(5) "title"
  [1]=>
  string(5) "title"
}

// In PHP 7.4 like these
//output 
array(6) {
  [-4]=>
  string(5) "title"
  [0]=>
  string(5) "title"
  [1]=>
  string(5) "title"
  [2]=>
  string(5) "title"
  [3]=>
  string(5) "title"
  [4]=>
  string(5) "title"
}
=> null
```
- Non-capturing catches [RFC](https://wiki.php.net/rfc/non-capturing_catches)
```php
//Before PHP 8
try {
    AddUser();
} catch (PermissionException $ex) {
    echo "You don't have permission to add user";
}

//PHP 8
try {
    AddUser();
} catch (PermissionException) {   //The intention is clear: exception details are irrelevant
    echo "You don't have permission to add user";
}
```
- ...

### 3. PHP 8 impact & compatibility (with Wordpress).
===
[Reference Link](https://developer.yoast.com/blog/the-2020-wordpress-and-php-8-compatibility-report/)

[Wordpress Version Compatibility](https://make.wordpress.org/core/handbook/references/php-compatibility-and-wordpress-versions/)

PHP 8 is a major update of PHP and WordPress aims to always be compatible with new versions of PHP.

Only a small percentage of the available plugins, the more popular and professionally developed ones, have automated tests in place.

PHP 7.* versions have seen a far larger set of deprecations than previous versions of PHP. Where PHP 5.6 to PHP 7 was a relatively simple migration, going from 7.x to 8 could be very painful, especially for very old codebases, the reality, however, is that WordPress is not such a codebase.

#### The test report is:

** Issues reported early on in the WP 5.6 dev cycle and fixed since based on PHPCompatibility scans:

- [Optional parameters declared before required parameters](https://core.trac.wordpress.org/ticket/50343)
- [Final private methods](https://core.trac.wordpress.org/ticket/50897)
- [Remove use of create_function](https://core.trac.wordpress.org/ticket/50899)
- [Only call libxmldisableentity_loader conditionally](https://core.trac.wordpress.org/ticket/50898)


** There are a large number of PHP warnings that have been changed to error exceptions in PHP 8. 

** Error level changes unrelated to RFC’s
The following warnings have been converted to errors probably related to deprecations in PHP 7.x versions:

- Attempting to write to a property of a non-object. Previously this implicitly created an stdClass object for null, false and empty strings.
- Attempting to append an element to an array for which the PHP_INT_MAX key is already used.
- Attempting to use an invalid type (array or object) as an array key or string offset.
- Attempting to write to an array index of a scalar value.
- Attempting to unpack a non-array/Traversable.

** Warnings coming from anywhere

PHP 8 is going to contain a lot of breaking changes and focusing so strongly on strict typing, WordPress’ type unsafe extensibility system also becomes extra vulnerable to errors, potentially leading to plugins causing type errors in other plugins or WordPress itself, many warnings that will turn into errors with PHP 8.

### 4. Deprecated

During the PHP 7.x release cycle, each version introduced new deprecations, which have now been finalized as feature removals in PHP 8. This also applies to some deprecation which were already put in place in PHP 5.x, but weren't removed in the PHP 7.0 release.

- php_errormsg.
- create_function().
- mbstring.func_overload.
- parse_str() without second argument.
- each().
- assert() with string argument.
- $errcontext argument of error handler.
- String search functions with integer needle.
- Defining a free-standing assert() function.
- The real type (alias for float).
- Magic quotes legacy.
- array_key_exists() with objects.
- Reflection export() methods.
- implode() parameter order mix.
- Unbinding $this from non-static closures.
- restore_include_path() function.
- allow_url_include ini directive.