Blogs

Blogs

From our minds to yours

PHP 8, 8.1 and 8.2 New Features and Comparisons

PHP 8 was officially released to General Availability on November 26, 2020.

This new major update brings many optimizations and powerful features to the language. There are many interesting changes that will allow developers to write better code and build more robust applications.

With PHP 8, there are a number of new features that make it a great fit for large-scale enterprise applications, including web services and microservices, and applications that run on the cloud.

The language also supports object-oriented programming, dynamic typing, and functional programming, which opens up new possibilities for developers.

PHP 8 is much faster than PHP 7 because of the new asynchronous design and JIT compiler, developers will be able to build asynchronous applications in PHP 8 which is a big deal for websites.

Let's discuss some of the new features.

Named Arguments:

PHP 8 has a new feature that allows you to specify the name of the argument in the method signature, which is useful when you have a lot of arguments in a method and you want to maintain the order of the arguments in your code. This causes the arguments to be order-independent, self-documented, and allows skipping optional ones. Named arguments are more useful when you want to increase the readability of your code.

PHP 7 :

<?php
  echo htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
?>

PHP 8 :

<?php 
  htmlspecialchars($string, double_encode: false);
?>

<?php
  class Maths{
    public function add($n1,$n2){
      return $n2+$n1;
    }
  }
?>

Attributes:

Attributes are used to decorate methods and functions, and have specific effects on the function. Attributes let you add metadata to your functions, classes and variables. This metadata can define the purpose of the function, the parameters it takes and more, making your code easier to read and understand.

PHP 7:

<?php
  Class Api{
  /**
    * @Route("/api/posts/{id}", methods={"GET"})
  */
   public function get($id) { /* ... */ }
  }
?>

PHP 8:

<?php
  class Api{
    #[Route("/api/posts/{id}", methods: ["GET"])]
    public function get($id) { /* ... */ }
  }
?>

Construction Property Promotions:

This feature is used to make properties getter and setters optional.

PHP 7 :

<?php
  class Person {
    public string $name;
    public string $age;
    public string $gender;
    public function __construct(
    string $name = 'somename',
    string $age = '20',
    string $gender = 'male'
    ) {
      $this->name = $name;
      $this->age = $age;
      $this->gender = $gender;
    }
  }
?>

PHP 8:

<?php
  class Person {
    public function __construct(
      public string $name = 'somename',
      public string $age = '20',
      public string $gender = 'male',
    ) {}
  }
?>

Union Types:

Prior to php 8.0 you could only declare a single type for properties, parameters, and return types. Union Type is a user-defined datatype which is a collection of all variables of different datatypes in the same memory location. To separate each datatype we use a vertical bar( | ) here.Union Type doesn't allow duplicate or redundant types in type declaration. These are checked at the compile time and will return in a syntax error.

PHP 7:

<?php
  class Number {
    /** @var int|float */
    private $number;
    /**
    * @param float|int $number
    */
    public function __construct($number) {
      $this->number = $number;
    }
  }
  $obj = new Number('NaN'); //This will work
?>

PHP 8:

<?php
  class Number {
  public function __construct(
    private int|float $number) {}
  }
  $obj = new Number('NaN'); // This will give TypeError
?>

Match Expression:

Most programming languages have some form of expression matching. In PHP 8, matching expressions are compiled to a native operation code. The new Match expression is similar to the switch statement. Its value can be returned or stored in a variable. It supports single-line expressions and does not need break statement.It does a strict comparison.

PHP 7:

<?php
  switch (1) {
  case '1':
    $result = "Not a Number";
    break;
  case 1:
    $result = "Its a Number";
    break;
  }
  echo $result;
?>

PHP 8:

<?php
  echo match (1) {
    '8.0' => "Not a Number", 8.0 => "Its a Number";
  }
?>

Null safe operator:

The nullsafe operator helps to prevent a Null Reference Exception. If there are multiple check for the null this operator can be used.

PHP 7:

<?php
  $country =  null;
  if ($session !== null) {
    $user = $session--->user;
    if ($user !== null){
    $address = $user->getAddress();
    if ($address !== null) {
      $country = $address->country;
    }
    }
  }
?>

PHP 8:

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

String to Number comparison:

There are two comparisons in PHP - Strict comparisons === and !== and the Non-strict comparisons ==, !=, >, >=, <, <= and ⇔. PHP 8 uses number comparison. Otherwise, it converts the number to a string and uses a string comparison.

PHP 7:

<?php
  0 == 'string' // true
?>

PHP 8:

<?php
  0 == 'foobar' // false
?>

Consistent type errors for internal functions:

PHP already throws TypeError in User-defined functions, but now in PHP 8, the internal functions the behavior has been made consistent.

PHP 7:

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

PHP 8:

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

Since its release there have been some upgrades in the php 8. We can compare these with php 8.1 and 8.2 versions of PHP 8. Some of the features can be listed out as following:

Enumerations:

Enumerations, or "Enums" allow a developer to define a custom type that is limited to one of a discrete number of possible values. That can be especially helpful when defining a domain model, as it enables "making invalid states unrepresentable."

PHP < 8.1

<?php
  class Status
    {
      const DRAFT = 'draft';
      const PUBLISHED = 'published';
      const ARCHIVED = 'archived';
    }
    function acceptStatus(string $status) {...}
?>

PHP 8.1

<?php
  enum Status
  {
    case Draft;
    case Published;
    case Archived;
  }
  function acceptStatus(Status $status) {...}
?>

Readonly Properties:

As of PHP 8.1.0, a property can be declared with the readonly modifier, which prevents modification of the property after initialization.

PHP < 8.1

<?php
    class BlogData
    {
    private Status $status;
    public function __construct(Status $status) 
    {
      $this--->status = $status;
    }
    public function getStatus(): Status
    {
      return $this->status;
    }
  }
?>

PHP 8.1

<?php
  class BlogData {
    public readonly Status $status;
    public function __construct(Status $status)
    {
      $this--->status = $status;
    }
  }
?>

First class callable syntax:

The first class callable syntax is introduced as of PHP 8.1.0, as a way of creating anonymous functions from callable.The advantage of this syntax is that it is accessible to static analysis, and uses the scope at the point where the callable is acquired.

PHP < 8.1

<?php
  $foo = [$this, 'foo'];
  $fn = Closure::fromCallable('strlen');
?>

PHP 8.1

<?php
  $foo = $this--->foo(...); $fn = strlen(...); 
?>

Pure Intersection Types:

Used when a value needs to satisfy multiple type constraints at the same time.

PHP < 8.1

<?php
  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);
  }
?>

PHP 8.1

<?php
  function count_and_iterate(Iterator&Countable $value) {
    foreach ($value as $val) {
      echo $val;
    }
    count($value);
  }
?>

Never return type:

A function or method declared with the never type indicates that it will not return a value and will either throw an exception or end the script’s execution with a call of die(), exit(), trigger_error(), or something similar.

PHP < 8.1

<?php
  function redirect(string $uri) {
    header('Location: ' . $uri);
    exit();
  }
  function redirectToLoginPage() {
    redirect('/login');
    echo 'Hello';
  }
?>

PHP 8.1

<?php
  function redirect(string $uri): never {
    header('Location: ' . $uri);
    exit();
  }
  function redirectToLoginPage(): never {
    redirect('/login');
    echo 'Hello'; 
  }
?>

Array unpacking support for string-keyed arrays:

PHP supported unpacking inside arrays through the spread operator before, but only if the arrays had integer keys. Now it is possible to unpack arrays with string keys too.

PHP < 8.1

<?php
  $arrayA = ['a' =--> 1]; $arrayB = ['b' => 2];
  $result = array_merge(['a' => 0], $arrayA, $arrayB); 
  output ['a' => 1, 'b' => 2] 
?>

PHP 8.1

<?php
  $arrayA = ['a' =--> 1]; 
  $arrayB = ['b' => 2]; 
  $result = ['a' => 0, ...$arrayA, ...$arrayB]; 
  // output ['a' => 1, 'b' => 2] 
?>

Fibers:

The fiber concept basically refers to a lightweight thread of execution (also called coroutine).They are a means of creating code blocks that can be paused and resumed like Generators, but from anywhere in the stack. Fibers themselves don't magically provide concurrency, there still needs to be an event loop. However, they allow blocking and non-blocking implementations to share the same API.

PHP < 8.1

<?php
  $httpClient--->request('https://example.com/') -> then(function (Response $response) { 
  return $response-> getBody()-> buffer(); }) -> then(function (string $responseBody) { 
  print json_decode($responseBody)['code']; }); 
?>

PHP 8.1

<?php
  $response = $httpClient--->request('https://example.com/'); 
  print json_decode($response-> getBody()-> buffer())['code'];
?>

We can list out some of the features of PHP 8.2 and compare it with PHP 8.1 as follows.

Readonly classes:

In php 8.1 the functions within the class could be Readonly, but with php 8.2 the class can be a readonly class. Marking a class as readonly will add the readonly modifier to every declared property, and prevent the creation of dynamic properties.

PHP < 8.2

<?php
  class BlogData
  {
    public readonly string $title;
    public readonly Status $status;
    public function __construct(string $title, Status $status) {
      $this--->title = $title; $this->status = $status; 
    }
  }
?>

PHP 8.2

<?php
  readonly class BlogData
    {
      public string $title;
      public Status $status;
      public function __construct(string $title, Status $status){
      $this-> title = $title; $this-> status = $status; 
    } 
  }
?>

Disjunctive Normal Form (DNF) Types:

DNF types allow us to combine union and intersection types, following a strict rule: when combining union and intersection types, intersection types must be grouped with brackets.

PHP < 8.2

<?php
  class Foo {
    public function bar(mixed $entity) {
    if ((($entity instanceof A) && ($entity instanceof B)) || ($entity === null)) {
      return $entity;
    }
    throw new Exception('Invalid entity');
    }
  }
?>

PHP 8.2

<?php
  class Foo {
    public function bar((A&B)|null $entity) {
    return $entity;
    }
  }
?>

Deprecate dynamic properties:

The creation of dynamic properties is deprecated, unless the class opts in by using the #[\AllowDynamicProperties] attribute. stdClass allows dynamic properties.

PHP < 8.2

<?php
  class User
  {
    public $name;
  }
  $user = new User();
  $user--->last_name = 'Doe'; 
?>

PHP 8.2

<?php
  class User
  {
      public $name;
  }
  $user = new User();
  $user--->last_name = 'Doe'; // Deprecated notice 
?>

Apart from the above mentioned features there are some New Classes, Interfaces, and Functions that have been introduced.

  • Weak Maps class
  • Stringable interface

Functions:

  1. str_contains()
  2. str_starts_with() and str_ends_with()
  3. preg_last_error_msg()
  4. get_debug_type()
  5. get_resource_id()

Just In Time Compilation

JIT in PHP 8 is a new extension for PHP 8 which lets you create JIT (Just In Time) compiled code within PHP. It is written in PHP and uses the Zend Engine II as a runtime. JIT-PHP 8's goal is to offer high performance for PHP applications by compiling the generated code into native machine code during runtime. JIT'd code runs fast and uses less memory, and it is much faster to load, so JIT is commonly used in complex web applications and even on mobile devices. JIT in PHP 8 makes it easy to create JIT'd code in PHP 8, and it offers a few different types of JIT to use, including JIT compiled PHP, JIT compiled JavaScript (called JITJS) and JIT compiled C++. Image Source

Conclusion:

In the above post we have covered the new features and improvements introduced in PHP 8. On the whole PHP 8 offers major improvements which will be more useful for all the PHP developers. Just In Time (JIT) is the most expected feature and in addition they have also improvised type systems which are brilliant.

Before migrating the entire application get a deep understanding from the migration guide on the PHP official documentation. Decide the way you wish to proceed with the performance and growth of your business.

LEAVE A COMMENT

Fields marked with an * are mandatory.