Published on

PHP 7.4 is coming!

Authors
Socials
Address
Company details

So, finally. They made it. One of my favorite PHP releases ever. Expecting new PHP 7.4 to be released late 2019. Let’s go trough all features we are going to get in PHP 7.4. I will be posting more deep topics about the features itself to explain them better later.


Typed Properties

If I need to start with something it will be this. I have been waiting for this feature long time already. With Typed properties you can specify what type the property is without needing to have getter/setters. What a nice feature! No more function overhead and private property just because you want be sure about that property being correct type.

php
class User {
    /** @var int $id */
    private $id;
    /** @var string $name */
    private $name;
 
    public function __construct(int $id, string $name) {
        $this->id = $id;
        $this->name = $name;
    }
 
    public function getId(): int {
        return $this->id;
    }
    public function setId(int $id): void {
        $this->id = $id;
    }
 
    public function getName(): string {
        return $this->name;
    }
    public function setName(string $name): void {
        $this->name = $name;
    }
}

Why would you do this anymore? Just by dropping these getters/setters you’re going to reduce the function overhead and calls. Just declare types directly into the Property and forgot functions.

php
class User {
    public int $id;
    public string $name;
 
    public function __construct(int $id, string $name) {
        $this->id = $id;
        $this->name = $name;
    }
}

I would also point this makes also PHPDoc useless. Why would we want anymore use PHPDoc and parse it in different kinda of libraries? No need for that anymore. I’m myself little bit against annotations, but due there is no better way to mark what type property is, it is the way to go. Now due you have been (hopefully) writing those annotations it will be easy to refactor for PHP 7.4.

Overall this feature will be making code much cleaner and easier to understand when you can see directly the type of the variable and really trust what you see. With PHPDoc you cannot always trust the property is what it says to you. Great!

Source: RFC: Typed Properties V2

Preloading

This might be also big hit. However, cannot say much as I have not ran any benchmark yet. As traditionally we have used to that PHP doesn’t need to be “compiled” to work. Instead of that we have run time compiler and we can cache the “compiled” code into memory by using OPCache.

OPCache should be mandatory on every production server and it gives huge performance boost as PHP doesn’t need to recompile code as same page is requested again and again. However, there is issues. OPCache checks if file is modified first, then we need to recompile it. This is ran on every request and causes some overhead. To also note, when PHP File is cached into memory it means the file is cached independently and class-dependencies need to be resolved on every run again and again.

Proposal, as seen in RFC, is to introduce new function to tell OPCache what to cache. This way you can for example cache your composer vendor folder. Looking some projects I do there might be 20k lines of code project itself and about 400k code in the vendor folder, this could benefit me a lot. In most of the cases libraries in vendor folder will stay anyways intact. There is example in RFC about implementing custom function to preload Zend Framework.

php
function _preload($preload, string $pattern = "/\.php$/", array $ignore = []) {
  if (is_array($preload)) {
    foreach ($preload as $path) {
      _preload($path, $pattern, $ignore);
    }
  } else if (is_string($preload)) {
    $path = $preload;
    if (!in_array($path, $ignore)) {
      if (is_dir($path)) {
        if ($dh = opendir($path)) {
          while (($file = readdir($dh)) !== false) {
            if ($file !== "." && $file !== "..") {
              _preload($path . "/" . $file, $pattern, $ignore);
            }
          }
          closedir($dh);
        }
      } else if (is_file($path) && preg_match($pattern, $path)) {
        if (!opcache_compile_file($path)) {
          trigger_error("Preloading Failed", E_USER_ERROR);
        }
      }
    }
  }
}
 
set_include_path(get_include_path() . PATH_SEPARATOR . realpath("/var/www/ZendFramework/library"));
_preload(["/var/www/ZendFramework/library"]);

// Example from RFC

Well, then raises question about how does this even differ form the automatically cached files by OPCache? Well, the main difference is, preloaded files remain cached in OPCache memory forever. If you modify files which are preloaded, nothing happens as it will not check anymore if the file is changed. You need to invalidate cache after modifying the files. This can be made by restarting the server.

By looking the future scope section there is actually one very interesting line.

It might be possible to pre-compile the preload script and use a binary-form (may be even native .so or .dll) to speed-up server start-up.

What does this mean? Code can be now encoded into .so/.dll and included into the PHP itself just as extension? Well, that pretty nice. Time will see what will happen. However when seeing this via commercial eye, I’m little bit worried more and more companies start shipping their proprietary code to the customers as a native extension when it will be impossible to view the code in case of problems or in case of switching the company.

Source: RFC: Preloading

Better return & param types.

This is one of my favorites also. In the “Harold” project I have been fighting with different kind of problems when doing abstractions. Return types are not compatible with the interface. Well, now it is “fixed” I can just override types in PHP 7.4. But to note, you cannot override with anything.

Let me introduce the Covariant returns and Contravarian parameters. Currently the problem is really simple and bellow code example will explain it much better than I will do with words. (Image Code is thousand words)

php
interface A {
  function m(B $z);
}
interface B extends A {
  // permitted
  function m($z): A;
}

Well, you see the problem there exactly. You cannot declare type for the function m in the interface B or you will get error. This RFC will be fixing these kind of problems.

In next example you can see how we override the return type.

php
interface Factory {
    function make(): object;
}
 
class UserFactory implements Factory {
    function make(): User;
}

This raises also the question about the return type being safe. Are we overriding types what we shouldn’t? My opinion into this it is type safe and you are overriding it probably for a reason. PHP is not a idiot proof language, you need to have attitude to write good code. That being said, I put it up to the developer to decide if the type override is really required.

This topic is really simple, but would need it’s own post to go trough fully how it works now and what are the goals to do about it in this RFC. I might be posting full topic about this in close future.

Source: RFC: Covariant Returns and Contravariant Parameters

Null Coalescing Assignment Operator Here I will expect, you’re already familiar of current Null Coalescing operator. The new operator aims just to extend the previous operator, but will be acting as assignment operator.

As background in PHP, there is short operators for almost everything to do with numbers, arrays etc.

php
$a += $b     $a = $a + $b    // Addition
$a -= $b     $a = $a - $b    // Subtraction
$a *= $b     $a = $a * $b    // Multiplication
$a /= $b     $a = $a / $b    // Division
$a %= $b     $a = $a % $b    // Modulus

// http://php.net/manual/en/language.operators.assignment.php#40084

This logic can be now accepted also into null coalescing operator. Now you can just used shorthand assignment in it. See the example.

php
// The following lines are doing the same
$this->data['comments'] = $this->['comments'] ?? 'value';
// Or by using shorthand
$this->request->data['comments'] ??= 'value';

This might not be a huge feature, but this is that small “work in progress” what is good to see from PHP language itself. The language have been developing a lot in OOP and basic features what other languages have.

Source: RFC: Null Coalescing Assignment Operator

Custom object serialization

This will be adding two new magic methods to fix core problems with PHP serialization. PHP current have two (__sleep,__wakeup,\Serializable) custom ways to implement custom serialization of objects, but both of those have problems. This third way to implement custom serialization should avoid all the problems previously mentioned ways to do the serialization have.

I’m not going to go here any deep what are the problems with the current methods to implement custom serialization, but it might be worth of a own topic itself.

The current proposal to fix these issues are to add methods “__serialize” and “__unserialize“. Usage of these methods are practically same as you would be implementing \Serializableinterface.

php
// Returns array containing all the necessary state of the object.
public function __serialize(): array;
 
// Restores the object state from the given data array.
public function __unserialize(array $data): void;

From PHP 7.4 onward I would recommend you to switch to use this way of serializing your objects, if you’re using any serialization. If you’re using \Serializable interface you should definitely think about refactoring your code as it is already considered to drop the \Serializable interface due the issues it have.

Source: RFC: New custom object serialization mechanism