4.35

PHP 8

Image
PHP 8.0 widely adopted by web developers, finally ! Be prepared for the next one: PHP 8.1 ... There are still a few number of developers that still rely on PHP 7.4 which will be soon EOL.

A new stable version of PHP has been released as of 26 November 2020 - PHP 8.0

The PHP development team announced one year ago the availability of PHP 8.0. PHP 7.4 is almost EOL (End of Life).


PHP 8 has already been adopted by most of web developers

This release marks the latest major release of the PHP language. PHP 8.0 is a major update of the PHP language.
It contains many new features and optimizations such as JIT, and improvements in the type system, error handling, and consistency.

PHP 8.0 comes with numerous improvements and new features such as:

  • Union Types
  • Named Arguments
  • Match Expressions
  • Attributes
  • Constructor Property Promotion
  • Nullsafe Operator
  • Weak Maps
  • Just In Time Compilation
  • And much much more...

PHP 8 migration guide

PHP 8 New Features Highlight

1. Any number of function parameters may now be replaced by a variadic argument, as long as the types are compatible. By example, the following code is now allowed:
<?php
class A {
     public function method(int $many, string $parameters, $here) {}
}
class B extends A {
     public function method(...$everything) {}
}

2. The static (as in "late static binding") can now be used as a return type:
<?php
class Test {
     public function create(): static {
          return new static();
     }
}

3. The throw can now be used as an expression. That allows usages like:
<?php
$fn = fn() => throw new Exception('Exception in arrow function');
$user = $session->user ?? throw new Exception('Must have user');

4. An optional trailing comma is now allowed in parameter lists:
<?php
function functionWithLongSignature(
    Type1 $parameter1,
    Type2 $parameter2, // <-- This comma is now allowed.
) {
}

5. The private methods declared on a parent class no longer enforce any inheritance rules on the methods of a child class (with the exception of final private constructors). The following example illustrates which restrictions have been removed:
<?php
class ParentClass {
    private function method1() {}
    private function method2() {}
    private static function method3() {}
    // Throws a warning, as "final" no longer has an effect:
    private final function method4() {}
}
class ChildClass extends ParentClass {
    // All of the following are now allowed, even though the modifiers aren't
    // the same as for the private methods in the parent class.
    public abstract function method1() {}
    public static function method2() {}
    public function method3() {}
    public function method4() {}
}


PHP 8 Deprecated Features Highlight

1. If a parameter with a default value is followed by a required parameter, the default value has no effect. This is deprecated as of PHP 8.0.0 and can generally be resolved by dropping the default value, without a change in functionality:
<?php
function test($a = [], $b) {} // Before
function test($a, $b) {}      // After

2. One exception to the above rule are parameters of the form Type $param = null, where the null default makes the type implicitly nullable. This usage remains allowed, but it is recommended to use an explicit nullable type instead:
<?php
function test(A $a = null, $b) {} // Still allowed
function test(?A $a, $b) {}       // Recommended

3. The sort comparison functions that return TRUE or FALSE will now throw a deprecation warning, and should be replaced with an implementation that returns an integer less than, equal to, or greater than zero:

<?php
// Replace
usort($array, fn($a, $b) => $a > $b);
// With
usort($array, fn($a, $b) => $a <=> $b);


PHP 8 Backward Incompatible Changes Highlight

1. Non-strict comparisons between numbers and non-numeric strings now work by casting the number to string and comparing the strings. Comparisons between numbers and numeric strings continue to work as before. Notably, this means that 0 == "not-a-number" is considered false now.
$test = (0 == "0");
var_dump($test); // Before: TRUE ; After: TRUE

$test = (0 == "0.0");
var_dump($test); // Before: TRUE ; After: TRUE

$test = (0 == "foo");
var_dump($test); // Before: TRUE ; After: FALSE !!!

$test = (0 == "");
var_dump($test); // Before: TRUE ; After: FALSE !!!

$test = (42 == " 42");
var_dump($test); // Before: TRUE ; After: TRUE

$test = (42 == "42foo");
var_dump($test); // Before: TRUE ; After: FALSE !!!

2. The @ operator will no longer silence fatal errors (E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR, E_PARSE). Error handlers that expect error_reporting to be 0 when @ is used, should be adjusted to use a mask check instead:
<?php
// Replace
function my_error_handler($err_no, $err_msg, $filename, $linenum) {
    if (error_reporting() == 0) {
        return; // Silenced
    }
    // ...
}

// With
function my_error_handler($err_no, $err_msg, $filename, $linenum) {
    if (!(error_reporting() & $err_no)) {
        return; // Silenced
    }
    // ...
}

3. The precedence of the concatenation operator has changed relative to bitshifts and addition as well as subtraction:
<?php
echo "Sum: " . $a + $b;
// was previously interpreted as:
echo ("Sum: " . $a) + $b;
// is now interpreted as:
echo "Sum:" . ($a + $b);

4. The precedence of the concatenation operator has changed relative to bitshifts and addition as well as subtraction:
<?php
echo "Sum: " . $a + $b;
// was previously interpreted as:
echo ("Sum: " . $a) + $b;
// is now interpreted as:
echo "Sum:" . ($a + $b);

5. Arguments with a default value that resolves to NULL at runtime will no longer implicitly mark the argument type as nullable. Either an explicit nullable type, or an explicit NULL default value has to be used instead:
<?php
// Replace
function test(int $arg = CONST_RESOLVING_TO_NULL) {}
// With
function test(?int $arg = CONST_RESOLVING_TO_NULL) {}
// Or
function test(int $arg = null) {}