Php 8.0

PHP 8.0 has been released on 26th November and come with a ton of new features and breaking changes. CyberPanel has added PHP 8.0 and all the currently available extensions. You can update your CyberPanel now and start testing your application to make it future proof.

PHP 8.0 is a major version which means it has been anticipated for years and it was under development for more than 2 years. This brings loads of changes to the type system, syntax, error handling, strings, object-oriented programming, and much more.

PHP 8.0 also introduces JIT ( Just in Time) compilation which makes it much easier and faster to run code that can be predicted.

So let’s start discussing significant changes and new features.


New Features

Constructor property promotion

The new version allows you to define and assign variables right in the constructor instead of having to define first, ask or set them in the constructor’s argument list and then assign the values.
So a typical PHP 7 or below class initialization code looks like this

class Point {  
    public int $x;  
    public int $y;  
    public int $z;  
    public function __construct(
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ) {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;  
    }  
}

With PHP 8 it can be shortened to this

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

Named Arguments

Before PHP 8.0 we could pass parameter as arguments but they had to be in order that they were defined in the function ( positional arguments ) and there was no way that you could pass them along with the name of the argument, so you always had to make sure that they were in order and it made writing code a bit difficult and more time-consuming. It was an additional nuisance to check for declaration whenever you had to debug.
For example in PHP 7 and below a typical function and its call would look like this

function str_contains(string $haystack, string needle): bool {
//code to find the needle in the haystack
}
str_contains('FooBar', 'Foo');

But if you mistakenly send the “needle” first or if you function has many arguments and you missed one of them you would be in trouble however from PHP 8.0 you can send the name along the argument too.

function str_contains(string $haystack, string $needle): bool {
//code to find the needle in the haystack
}
str_contains(haystack: 'FooBar', needle: 'Foo');

You could also send the named arguments in different order and it would still work

function str_contains(string $haystack, string $needle): bool {
//code to find the needle in the haystack
}
str_contains(needle: 'Foo', haystack: 'FooBar');

As you can understand this could help make the code easier to write, understand and debug.

Null-safe Operator

We have all been there when we have to add a extra check to make sure something is present in the any object before calling a pointer or a nested pointer if we don’t want a missing info resulting in a fatal error

PHP 8.0 adds a null safe operator to → to provides safety in method/property chaining when the return value or property can be “null”

In PHP 7 and below we had to do something like this

$country =  null;

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

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

With PHP 8 it can be done in a single line like this

return $user->getAddress()?->getCountry()?->isoCode;

The ?-> null-safe operator short-circuits the rest of the expression if it encounters a null value, and immediately returns null without causing any errors.

Attributes

Atrributes or meta-data annotations are one of the biggest changes in PHP 8.0. Till this version PHPdoc was used to add comments, now we can attributes which can be fetched programmatically when declared using “use” keyword and reflection API

This can be done using << >> operators instead of using *@ method

Here is a complete example

use App\Annotations\FooAttribute;
use App\Annotations\ClassAttrib as FooClassAttrib;
use App\Annotations\FooParamAttrib;
use External\Attr\BarClassAttrib;

<<App\Annotations\FooAttribute>>
function foo_func(<<FooParamAttrib('Foo1')>> $foo) {}

<<FooAttribute('hello')>>
<<BarClassAttrib(42)>>
class Foo {
    <<ConstAttr>>
    <<FooAttribute(null)>>
    private const FOO_CONST = 28;
    private const BAR_CONST = 28;

    <<PropAttr(Foo::BAR_CONST, 'string')>>
    private string $foo;

    <<SomeoneElse\FooMethodAttrib>>
    public function getFoo(<<FooClassAttrib(28)>>): string{}
}

JIT ( Just in time ) Compilation

JIT is arguably the biggest change that has been added to PHP 8. In a compiled language, the source code is converted to computer-readable code ahead of time. Interpreted languages, on the other hand, convert the source code as it’s executed, which is much slower. PHP is an interpreted language, and there have been several tactics used to improve PHP performance in the past with the latest step is the addition of the JIT compiler in PHP 8.

The JIT compiler is a middle ground between compilation and interpretation. It will compile and cache some sections of code at runtime so that the compiled version can be used instead of the interpreted version. This could lead to huge performance gains for PHP, but with some caveats. Generally, JIT compilers mostly benefit CPU-intensive applications, such as 3D rendering or large mathematical computations. If you’re using PHP for web applications, you may not see a substantial performance boost by enabling the JIT compiler.

PHP team has shared some results which show improvement in processing speed for synthetic benchmarks

However one of the developer says the following

it currently doesn’t seem to significantly improve real-life apps like WordPress (with opcache.jit=1235 326 req/sec vs 315 req/sec).

It’s planned to provide additional effort, improving JIT for real-life apps, using profiling and speculative optimizations.”

So we might have to wait a few more version to see the results on web apps like Wordpress or Laravel based apps.

throw as an expression

Prior to PHP 8.0, throw was a statement and it was not allowed to throw an exceptions in when a single expression is expected. It is now possible to throw an exception in arrow functions, ternary expressions, or anywhere else the PHP parser expects a single expression.

Arrow Functions:

$fn = fn() => throw new \Exception('oops');

Ternary expressions:

$value = isset($_GET['value'])
? $_GET['value']
: throw new \InvalidArgumentException('value not set');

$value ??= throw new \InvalidArgumentException('value not set');

$foo = $bar ?: throw new \InvalidArgumentException('$bar is falsy');

$foo = $bar ?? throw new \InvalidArgumentException('$bar is not set');

Match expression

Switch statement gets and elder more powerful sister called match. Its an expression so the results can be stored. Although it does strict comparison only.

So a switch statement like this in 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!

Can now be written as

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

String functions

PHP 8.0 comes with better string search but its only string sensitive and save you from add !== to strops() function

Without this function, the usual way to find if a given string contains another string is to use to the strpos() function:

if (strpos(‘Foo Bar Baz’, ‘Bar’) !== false) {
echo ‘Found’;
}

strpos() function returns the position of the needle string, or false if the needle is not found. This is error-prone, because if the needle is found at the position 0 of the haystack, it evaluates to false unless strict comparison (===) used.

To explain further, the following snippet is not correct:

if (strpos('Foo Bar Baz', 'Foo')) {
echo 'Found';
}

Because Foo is found at the beginning of the haystack, the return value of strpos() call will be 0, which evaluates to false, and the if block will not run.

With the new str_contains function, it is easy to do this:

if (strpos('Foo Bar Baz', 'Foo')) {
echo 'Found';
}

Similarly, two more string functions are added to check if the string begins or ends with another string

str_starts_with to determine if a string starts with another string and str_ends_with to determine if the string ends with another string

str_starts_with (string $haystack, string $needle): bool;
str_ends_with (string $haystack, string $needle): bool;

Deprecations and removals

  • PostgreSQL: Several aliased functions are deprecated
  • Deprecate required parameters after optional parameters in function/method signatures
  • ReflectionParameter::getClass()), ::isArray(), and ::isCallable() methods deprecated
  • Disabled functions: Reflection and get_defined_functions() deprecations
  • libxml_disable_entity_loader function is deprecated
  • XMLRPC extension is moved to PECL
  • FILTER_FLAG_SCHEME_REQUIRED and FILTER_FLAG_HOST_REQUIRED flags are removed

Adding PHP 8 to Cyberpanel

Installing PHP 8 to Cyberpanel is simple and easy. Just run the upgrade command and it will be installed for you. In case you don’t know how to update, please follow this guide

https://cyberpanel.net/docs/upgrading-cyberpanel/

Still not using CyberPanel? Well, you are missing out a lot. CyberPanel provide 1-Click installers for all major server providers and a single command to install if you are using something else. So what are you waiting for?

Can we install php 7.4 and php 8 in same server?

It is already installed by default in Cyberpanel.