Loading

PHP 8.0 - New features

PHP 8.0 - New features

PHP 8.0 is released with major updates which brings a lot of powerful features and optimization techniques which includes named arguments, union types, attributes, constructor property promotion, match expression, nullsafe operator, JIT, and improvements in the type system, error handling etc. We are very excited to drive you through the most interesting changes that will allow us to write better code and build more powerful applications in PHP language.

Just-In-Time compilation

The most interesting and major change in PHP 8 is the JIT compiler. The JIT compiler compiles and executes minimum code, a lot like keeping in a cache. Previously, PHP was an interpreted language. The JIT compiler is much faster than the interpreter. So it would not be wrong to think that now PHP will work much faster than before. PHP 8 introduces us to two different JIT engines. One is Tracing JIT and the other is Function JIT. PHP's official website claims that it is giving 3 times more performance in synthetic benchmarking and 1.5 to 2 times more performance in long-running applications.

jit.svg

Named arguments

PHP 7:

htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);

PHP 8:

class PostsController
htmlspecialchars($string, double_encode: false);

Attributes

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) { /* ... */ }
}

Constructor property

PHP 7:

class Point {
  public float $x;
  public float $y;
  public 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;
  }
}

PHP 8:

class Point {
  public function __construct(
    public float $x = 0.0,
    public float $y = 0.0,
    public float $z = 0.0,
  ) {}
}

You may also like: Handle CORS error in Lumen

Union types

PHP 7:

class Number {
  /** @var int|float */
  private $number;

  /**
   * @param float|int $number
   */
  public function __construct($number) {
    $this->number = $number;
  }
}

new Number('NaN'); // Ok

PHP 8:

class PostsController
htmlspecialchars($string, double_encode: false);

Named arguments

PHP 7:

htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);

PHP 8:

class Number {
  public function __construct(
    private int|float $number
  ) {}
}

new Number('NaN'); // TypeError

Match expression

PHP 7:

switch (8.0) {
  case '8.0':
    $result = "Oh no!";
    break;
  case 8.0:
    $result = "This is what I expected";
    break;
}
echo $result;
//> Oh no!

PHP 8:

echo match (8.0) {
  '8.0' => "Oh no!",
  8.0 => "This is what I expected",
};
//> This is what I expected

Nullsafe operator

PHP 7:

$country =  null;

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

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

    if ($address !== null) {
      $country = $address->country;
    }
  }
}

PHP 8:

$country = $session?->user?->getAddress()?->country;

Saner string to number comparisons

PHP 7:

0 == 'foobar' // true

PHP 8:

0 == 'foobar' // false

Consistent type errors for internal functions

PHP 7:

strlen([]); // Warning: strlen() expects parameter 1 to be string, array given

array_chunk([], -1); // Warning: array_chunk(): Size parameter expected to be greater than 0

PHP 8:

strlen([]); // TypeError: strlen(): Argument #1 ($str) must be of type string, array given

array_chunk([], -1); // ValueError: array_chunk(): Argument #2 ($length) must be greater than 0

You may also like: Creating a JWT Authenticated REST API with Lumen

Type System and Error Handling Improvements

There have been many changes to the typing system in PHP 8 and those changes will affect your coding experience in many ways. So let's take a look at the new features that come with handling PHP 8 type systems and errors.

  • Prior to PHP 8, arithmetic and bitwise operators also worked on arrays, objects and resources. But now it is no longer possible.
  • PHP 8 has added abstract method validation to Trait. Now if you define an abstract method in Trait, you have to implement it using the proper signature in class.
  • In the case of the magic method, it is now mandatory to follow the proper signature, otherwise, the compiler will throw an error.

Before PHP 8, there were many types of errors that simply threw a warning. Now they will throw proper error. Such as -

  • Undefined variable: Error exception instead of notice
  • Undefined array index: warning instead of notice
  • Division by zero: DivisionByZeroError exception instead of warning
  • Attempt to increment/decrement property '%s' of non-object: Error exception instead of warning
  • Attempt to modify property '%s' of non-object: Error exception instead of warning
  • Attempt to assign property '%s' of non-object: Error exception instead of warning
  • Creating default object from empty value: Error exception instead of warning
  • Trying to get property '%s' of non-object: warning instead of notice
  • Undefined property: %s::$%s: warning instead of notice
  • Cannot add an element to the array as the next element is already occupied: Error exception instead of warning
  • Cannot unset offset in a non-array variable: Error exception instead of warning
  • Cannot use a scalar value as an array: Error exception instead of warning
  • Only arrays and Traversables can be unpacked: TypeError exception instead of warning
  • Invalid argument supplied for foreach(): TypeError exception instead of warning
  • Illegal offset type: TypeError exception instead of warning
  • Illegal offset type in isset or empty: TypeError exception instead of warning
  • Illegal offset type in unset: TypeError exception instead of warning
  • Array to string conversion: warning instead of notice
  • Resource ID#%d used as offset, casting to integer (%d): warning instead of notice
  • String offset cast occurred: warning instead of notice
  • Uninitialized string offset: %d: warning instead of notice
  • Cannot assign an empty string to a string offset: Error exception instead of warning
  • A supplied resource is not a valid stream resource: TypeErrorexception instead of warning
  • In the case of inheritance, if any method is incompatible then Fatal will show an error.
  • @ The operator will no longer block Fatal Error.
  • Prior to PHP 8, private method checks were like a public or protected which had no meaning. Because access to the private method is not possible in child class. This check is newly installed in PHP 8.
  • A new type called mixed has been added to PHP 8. mixed means it can contain any type of data.
  • Static type can be returned from a function in PHP 8.

New Classes, Interfaces & Functions

Weak Map

Weak map is a type of data structure that retains the reference of the object and protects that object from the hands of the garbage collector.

class Foo 
{
    private WeakMap $cache;

    public function getSomethingWithCaching(object $obj): object
    {
        return $this->cache[$obj]
           ??= $this->computeSomethingExpensive($obj);
    }
}

Stringable Interface

This is a new interface of PHP 8. Anything that implements the __toString() method uses Stringable Interface behind the scenes.

class Foo
{
    public function __toString(): string
    {
        return 'foo';
    }
}

function bar(string|Stringable $stringable) {}

bar(new Foo()); // Stringable
bar('abc');

New str_contains(), str_starts_with() & str_ends_with()

// str_contains() check if the substring contains in the given string
str_contains('Stack Learner Nano Camp is Running', 'Nano Camp') // true

str_starts_with('Stack Learner', 'Stack'); // true
str_ends_with('Stack Learner', 'Learner'); // true  

New fdiv() Function

This function will return INF, -INF or NAN instead of throwing errors when something is divided by 0.

New get_debug_type() Function

This function is a lot like the gettype() function, but the get_debug_type () function returns a lot of information.

New get_resource_id() Function

Resource in PHP is a special variable, such as MySQL Connection or file handle. Typecasting was required to get the resource ID in PHP 7. Now the get_resource_id() function will do the job of getting that ID.

$resourceId = (int) $resource; // PHP 7
$resourceId = get_resource_id($resource); // PHP 8

New token_get_all() Function

This function is a special function created for an object whose function is to return the values ​​of the object to an array. This function has been newly optimized and implemented for the object only.

Other Syntax Tweaks & Improvements

Allow Trailing Comma in Parameters

So far we could use trailing commas during function invoking or calling. From PHP 8 we can also use trailing commas in parameters when defining functions.

public function(
    string $parameterA,
    int $parameterB,
    Foo $objectfoo, // trailing comma
) {}

Non-Capaturing Catches

Now we don't need to store the error into a variable what we have done before.

/* PHP 7 */
try {
  // DO Something
} catch (Exception $e) {
  Log::error("Error");
}

/* PHP 8 */
try {
  // Do Something
} catch {
  Log::error("Error");
}

Now Throw is An Expression

$triggerError = fn () => throw new MyError();

$foo = $bar['offset'] ?? throw new OffsetDoesNotExist('offset');

Allowing ::class on Objects

Now we can use ::class directly with an object instead of using get_class().

$foo = new Foo();
var_dump($foo::class);

You may also like: Creating a REST API with Lumen

Related Articles