Introducing PHP 7.4: Performance, Features, Deprecations

What Does PHP 7.4 Mean for You?


PHP evolves continuously and they just released their latest PHP 7.4 update, full of new features. As we have already been proved in the past PHP 7 releases – performance and speed keep advancing. One of the most exciting new features is preloading. It quickens script execution and introduces the ability to have faster and cleaner code because of the simplified common lines of code.

People in charge of PHP took their audience’s comments and requests into a maximum consideration and answered them flawlessly. They have since been continuously changing code to be more intuitive and more comfortable to switch between programming languages.

PHP is used in over 78.9% of all websites. According to W3techs, the most popular sites using PHP are Wikipedia, Pinterest, and Facebook, to name a few.

If we explicitly look at WordPress sites running PHP, comparing PHP 5 and 7, we can see a double speed increase. WordPress powered websites gain the most by using the latest PHP version out there.

image

This graph illustrates the truth about websites actively using PHP. Are 40 mln. live websites enough to grab your attention? That’s how many are using PHP right now. Additionally, PHP 7.4 is already presenting better test results than PHP 7.3 with improved performance and other quality of life upgrades.

The graph below shows the overall benchmark test on new and old versions of PHP. Some of the criteria tested were ease of use, speed, and performance among others.

image

What’s New in PHP 7.4?


Since 2016, PHP7 has been releasing annual updates without fail. Each year they deliver on new features, additions, and the possibility to write cleaner code that makes the language more reliable and user-friendly for those who run it on their websites.

Let’s dig in and take a closer look at some of the changes that were made with the addition of PHP 7.4. For a full list, check out their changelog here.

Preloading


Let’s talk about code. When using a framework or libraries, its files have to be loaded and linked on every request. Preloading is when you can load frameworks and libraries into the OPCache. It allows for the server to load the PHP files and store them in memory during startup and have them available for any future requests. Talk about getting things going quick!

Preloading is run by a specific php.ini directive: opcache.preload. This has the PHP script compiler and executes when the server starts-up. It can also be used to preload more files and choose to either include or compile them.

This is awesome. However, if the source of the preloaded files is ever changed, the server must be restarted. The preloaded files also remain cached in OPCache memory forever.
However, these preloaded files will continue to be available for any future requests in case you ever need to use them again.

Spread Operator in Array Expressions


Back when PHP 5.6 was released, PHP began supporting argument unpacking (spread operator), but now, with 7.4, we can use this feature with an array expression. Argument unpacking is a syntax for unpacking arrays and Traversables into argument lists. And, to do so, it only needs to be prepended by … (3 dots.) That’s it.

Let’s look at this example:

$animals = ['dog', 'cat'];
$animalkingdom = ['lion', 'elephant', ...$animals, 'giraffe'];
// [‘lion’, ‘elephant’, ‘dog’, ‘cat’, ‘giraffe’];

We can now expand an array from anywhere we want in another array, by simply using the Spread Operator syntax.

Here is a longer example:

$num1 = [1, 2, 3];
$num2 = [...$num1]; // [1, 2, 3]
$num3 = [0, ...$num1]; // [0, 1, 2, 3]
$num4 = array(...$num1, ...$num2, 111); // [1, 2, 3, 1, 2, 3, 111]
$num5 = [...$num1, ...$num1]; // [1, 2, 3, 1, 2, 3]

Not only that, but you can also use it in a function. Check out this example:

function getNum() {
  return ['a', 'b'];
}
$num6 = [...getNum(), 'c']; // ['a', 'b', 'c']
 
$num7 = [...new NumIterator(['a', 'b', 'c'])]; // ['a', 'b', 'c']
 
function arrGen() {
    for($i = 11; $i < 15; $i++) {
        yield $i;
    }
}
$num8 = [...arrGen()]; // [11, 12, 13, 14]

In addition, you are now able to unpack arrays and generators that are returned by a function directly into a new array.

A code example would look like this:

function getAnimals(){
return ['dog', 'cat', 'elephant'];
}
$num1 = [...getAnimals(), 'lion', 'tiger', 'giraffe'];

And with PHP 7.4, it would print:

array(6) {
[0]=>
string(3) "dog"
[1]=>
string(3) "cat"
[2]=>
string(8) "elephant"
[3]=>
string(4) "lion"
[4]=>
string(5) "tiger"
[5]=>
string(7) "giraffe"
}

With this new array expression, spread operators should have way better performance over the 7.3 array_merge. This is because the spread operator is a language structure while array_merge is a function. Also because spread operator supports objects implementing traversable and array_merge only supports arrays.

Some important things to note, you can only use indexed arrays since string keys are not supported. If used, a recoverable error will be thrown on the screen, once a string key is found.
Another glorious benefit to 7.4 is the removal of the array_merge. Say goodbye to the dreaded index shift!

For example, let’s look at this long winded array merge below:

$array = [‘banana, ‘orange’];
$array[2] = ‘orange’;
$array[1] = ‘apple’; //shifting
var_dump($array);
// prints
array(3) {
[0]=>
string(6) "banana"
[1]=>
string(5) "apple"
[2]=>
string(6) "orange"

Another benefit of 7.4 is using the generator function. A generator function works just like a normal function, except instead of returning a value, a generator function yields as many values as it needs to.

Check out the example code below:

function generator() {
for ($i = 3; $i <= 5; $i++) {
yield $i;
}
}
$num1 = [0, 1, 2, ...generator()];

Weak References


Now PHP 7.4 has a WeakReference class, which is not to be confused with the class WeakRed or the Weakref extension.

WeakReferences let the programmer recall a reference to an object. This is useful because it doesn’t prevent the object from being destroyed. They are helpful for implementing cache like structures.

WeakReference {
/* Methods */
public __construct ( void )
public static create ( object $referent ) : WeakReference
public get ( void ) : ?object
}

Contravariant Parameters and Covariant Returns


Currently, PHP uses mostly invariant parameter types and return types. Meaning, if a method has a parameter or return type of X then the subtype parameter or return type must also be type X.

Now, with PHP 7.4 it proposes to allow covariant (ordered from specific to generic) and contravariant (reversing the order) on parameter and return types.

Here is an example of both:

Covariant return type example:

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

Contravariant parameter type example:

interface Concatable {
function concat(Iterator $input);
}
class Collection implements Concatable {
// accepts all iterables, not just Iterator
function concat(iterable $input) {/* . . . */}
}

Typed Properties 2.0


Since PHP 5, type hints have been an available feature allowing you to specify the type of variable that is expected to be passed to a function or class. In the PHP 7.2 migrations, the addition of the object data type gave hope that more would be available in the future. The future is now.

In the new 7.4, PHP is able to support the following type list:

bool, int, float, string, array, object, iterable, self, parent
any class or interface name
?type // where "type" may be any of the above

Note that the parent type can be used in classes and does not need to have a parent consistent with the parameter and return type.

Also, note that void and callable are not supported. Void was removed because it was not useful and had unclear semantics; Callable, because its behavior was context-dependent.

Let’s check out some more examples.

Here is a class, written for PHP 7.3:

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;
    }
}

In PHP 7.4, without sacrificing any type-safety, a class can now be written as simple as:

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

Here are some examples of all the types 7.4 now supports:

class Example {
  
    public int $scalarType;
    protected ClassName $classType;
    private ?ClassName $nullableClassType;
 
    // Types are also legal on static properties
    public static iterable $staticProp;
 
    // Types can also be used with the "var" notation
    var bool $flag;
 
    // Typed properties may have default values (more below)
    public string $str = "foo";
    public ?string $nullableStr = null;
 
    // The type applies to all properties in one declaration
    public float $x, $y;
    // equivalent to:
    public float $x;
    public float $y;
}

Arrow Functions 2.0


Anonymous functions in PHP tend to be wordy and lengthy, even when they are only performing simple operations. This is partially due to a large amount of syntactic boilerplate, and partially due to the need to manually import used variables.

This makes code that uses simple closures confusing to read and even harder to understand.

Let’s look at some code that you would use with PHP 7.3:

function array_values_from_keys($arr, $keys) {
    return array_map(function ($x) use ($arr) { return $arr[$x]; }, $keys);
}

Now, here is the more concise syntax of PHP 7.4:

function array_values_from_keys($arr, $keys) {
    return array_map(fn($x) => $arr[$x], $keys);
}

Therefore, arrow functions now have this simple form:

fn(parameter_list) => expr

Below you can see an example of two functions $fn1 (7.3) and $fn2 (7.4) side by side. They have the same outcome but look different:

$y = 1;
$fn1 = fn($x) => $x + $y;
 
 
$fn2 = function ($x) use ($y)
{
    return $x + $y;
};

This will also work if the arrow functions are nested:

$z = 1;
$fn = fn($x) => fn($y) => $x * $y + $z;

Here the outer function captures $z. Then, the inner function also captures $z from the outer function. With 7.4, the outer scope can become available in the inner function. This is something 7.3 wasn’t able to do.

The arrow function syntax allows for a variety of functions such as, variadics, default values, parameter and return types, as well as by-reference passing and returning. All while keeping a clean, readable look. Below are all the valid arrow functions now available:

fn(array $x) => $x;
fn(): int => $x;
fn($x = 42) => $x;
fn(&$x) => $x;
fn&($x) => $x;
fn($x, ...$rest) => $rest;

One thing to note is that arrow functions have the lowest precedence. See the example:

fn($x) => $x + $y
// is
fn($x) => ($x + $y)
// not
(fn($x) => $x) + $y

Deprecations


There are many deprecations happening with the merge to 7.4. The following list is a short overview of the functions targeted for deprecation. You can find a more detailed explanation here:

  • The real type
  • Magic quotes legacy
  • array_key_exists() with objects
  • FILTER_SANITIZE_MAGIC_QUOTES filter
  • Reflection export() methods
  • mb_strrpos() with encoding as 3rd argument
  • implode() parameter order mix
  • Unbinding $this from non-static closures
  • hebrevc() function
  • convert_cyr_string() function
  • money_format() function
  • ezmlm_hash() function
  • restore_include_path() function
  • allow_url_include ini directiv

Some important ones to note are the following two-step deprecations.

Changing the Precedence of a Concatenation Operator


Currently the precedence of ‘.’, ‘+’ and ‘-‘ operators are all equal. Any combination of these operators will simply be solved from left-to-right.

Let’s look at this code in PHP 7.3:

echo "sum: " . $a + $b;
// would be evaluated left-to-right
echo ("sum: " . $a) + $b;
// could also look like this

With PHP 7.4, ‘+’ and ‘-’ would take precedence over ‘.’ so the additions and subtractions would always be performed before the string. This would look like the following:

echo "sum: " . $a + $b;
// would be executed as if the code were as follows.
echo "sum :" . ($a + $b);

This two-step proposal aims to be less error-prone and more instinctive. PHP 7.4 currently is in the first stage with a deprecation notice of un-parenthesized expressions of ‘+’, ‘-’ and ‘.’ While waiting for the final vote/change happening in PHP 8.

Left-Associative Ternary Operator


Unlike most other languages, the ternary operator in PHP is left-associative rather than right-associative. Not only being uncommon, it is also confusing for programmers who switch between different languages. PHP 7.4 proposes to remove the left-associativity and requires the use of parentheses instead.

Let’s take a look at the code below:

return $a == 1 ? 'one'
 	: $a == 2 ? 'two'
 	: $a == 3 ? 'three'
 	: $a == 4 ? 'four'
           	: 'other';

In most other languages it would be interpreted as:

return $a == 1 ? 'one'
 	: ($a == 2 ? 'two'
 	: ($a == 3 ? 'three'
 	: ($a == 4 ? 'four'
           	: 'other')))

While in PHP, it is instead interpreted as:

return ((($a == 1 ? 'one'
 	: $a == 2) ? 'two'
 	: $a == 3) ? 'three'
 	: $a == 4) ? 'four'
           	: 'other';

This can lead to errors because it’s generally not what was intended.

Through a separate two-step proposal, PHP 7.4 has implemented the explicit use of parentheses as a deprecation warning and will hopefully carry out a compile runtime error in future versions.

Conclusion


Just in time for the holidays, PHP 7.4 brings new features and quality of life improvements for all PHP developers.

WordPress websites will definitely benefit from these improvements and their users can expect faster execution times and less memory usage when using PHP 7.4 compared with previous versions.

With the addition of first-class property type declarations and type hinting, arrow merging functions, and ridiculously better speed, the 7.4 will surely improve both the speed and quality of your workflow.
Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 0

Only users with full accounts can post comments. Log in, please.