PHP 7

PHP Usergroup Leipzig

Februar 2016

Christian Weiske

PHP 7

PHP 7.0

Release 03.12.2015
2 Jahre Support bis 03.12.2017
+1 Jahr Sicherheitspatches bis 03.12.2018

Andere PHP-Versionen

Ref: php.net: Supported Versions

PHP6?

Ref:

Performance

System PHP 5.6 PHP 7.0 HHVM
Wordpress 4.4 270 604 624
Drupal 8 1401 2580 1881

(Anfragen pro Sekunde)

Ref:

Codebeispiele

Namespaces: use gruppieren

Zusammenfassung von Imports:

<?php
use foo\bar\{
    A,
    B\C,
    D as E
};
?>

Ref: Group use declarations

Throwable + Error 1/4

Ref:

ParseError 2/4

<?php
try {
    include 'syntax_error.php';
} catch (Throwable $e) {
    echo 'Caught ' . get_class($e) . ': ' . $e->getMessage() . "\n";
}
Caught ParseError: syntax error, unexpected ';',
expecting identifier (T_STRING) or function (T_FUNCTION)
or const (T_CONST) or \\ (T_NS_SEPARATOR)

Throwable-Hierarchie 3/4

interface Throwable
  |- Exception implements Throwable
  |   \- ...
  \- Error implements Throwable
      |- TypeError extends Error
      |- ParseError extends Error
      |- ArithmeticError extends Error
      |   \- DivisionByZeroError extends ArithmeticError
      \- AssertionError extends Error

Einfluss auf alten Code 4/4

<?php
function exceptionHandler(Exception $e) {}
set_exception_handler('exceptionHandler');
1 % 0;
PHP Fatal error:  Uncaught TypeError: Argument 1 passed
to exceptionHandler() must be an instance of Exception,
instance of DivisionByZeroError given

Skalare Variablentypen 1/3

Ref:

Automatische Konvertierung 2/3

<?php
function foo(int $num, string $str, float $amount, bool $really)
{
    var_dump(func_get_args());
}
foo("1.2", 1.2, 1, 10);

Ausgabe:

array(4) {
    [0] => int(1)
    [1] => string(3) "1.2"
    [2] => float(1)
    [3] => bool(true)
}

Strikte Typenprüfung 3/3

<?php
declare(strict_types=1);
function foo(int $num) {}
foo(1.2);
PHP Fatal error:  Uncaught TypeError: Argument 1 passed
to foo() must be of the type integer, float given

Rückgabetypen 1/2

Automatische Umwandlung:

<?php
function foo(): int
{
    return 1.2;
}
var_dump(foo());
int(1)

Ref: php.net: return type declaration

Rückgabetypen 2/2

Strikte Typenprüfung:

<?php
declare(strict_types=1);
function foo(): int
{
    return 1.2;
}
var_dump(foo());
PHP Fatal error:  Uncaught TypeError:
Return value of foo() must be of the
type integer, float returned

Null coalescing operator ??

Wenn man mit isset und !null prüfen müsste:

<?php
$user  = $_SERVER['NAME'] ?? 'default';
$user2 = $_SERVER['NAME'] ?? $_SERVER['USER'] ?? 'default';
echo $user . ' / ' .  $user2 . "\n";
$ php7 code/null-coalescing.php
default / cweiske
$ NAME=foo php7 code/null-coalescing.php
foo / foo

Ref: php.net: Comparison operators

Raumschiffoperator

Spaceship operator - für Vergleichsfunktionen:

<?php
function compare($a, $b)
{
    return $a <=> $b;
}
$data = [2,1,3];
usort($data, 'compare');
var_dump($data);
array(3) { int(1), int(2), int(3) }

Kann man in PHP 5.x mit $a - $b abbilden.

Ref: php.net: Comparison operators

Anonyme Klassen

Der gleiche Mist wie in JavaScript:

<?php
$obj->setLogger(new class implements Logger{function log($msg, $severity){echo $msg."\n";}});

$obj->setLogger(
    new class implements Logger {
        function log($msg, $severity) {
            echo $msg . "\n";
        }
    }
);

Erlaubte Klassen in unserialize

Zur Absicherung, damit man keine Code Injections bekommt:

<?php
$data = unserialize(
    $_COOKIE['foo'],
    ['allowed_classes' => ['ClassA', 'ClassB']]
);

alle erlauben:

<?php array('allowed_classes' => true)

Nicht erlaubte Klassen werden zu __PHP_Incomplete_Class.

Generatoren 1/3

<?php
function loadCsvValues($file) {
    $hdl = fopen($file, 'r');
    while ($row = fgetcsv($hdl, 1024, ':')) {
        yield $row;
    }
}
foreach (loadCsvValues('/etc/passwd') as $row) {
    echo $row[0] . "\n";
}

Generatoren: Verschachtelung 2/3

<?php
function getAttributes(SimpleXMLElement $sx)
{
    foreach ($sx->attributes() as $name => $val) {
        yield $name;
    }
    foreach ($sx->children() as $child) {
        yield from getAttributes($child);
    }
}
$sx = simplexml_load_file(__DIR__ . '/../slides.html');
foreach (getAttributes($sx) as $attrib) {
    echo $attrib . "\n";
}

Ref: php.net: generator syntax

Generatoren: Rückgabewert 3/3

<?php
$gen = (
    function() {
        yield 1;
        return 2;
    }
)();
foreach ($gen as $val) {
    var_dump($val);
}
var_dump($gen->getReturn());
int(1)
int(2)

Ref: php.net: generator syntax example

Session: read and close

<?php
session_start(['read_and_close' => true]);

Hilft sehr bei gleichzeitigen Zugriffen eines Browsers, was bisher zu Session-Lock-Problemen geführt hat.

Ref: php.net: session_start()

E_STRICT

Ref: php.net: E_STRICT error handling in PHP7

foreach

Strings

Entfernte Funktionen

Ref: php.net: removed functions in PHP7

Tiefe in dirname()

<?php
$parent      = dirname(__FILE__);
$grandparent = dirname(__FILE__, 2);
$somewhere   = dirname(__FILE__, 255);
var_dump(__FILE__, $parent, $grandparent, $somewhere);
string(61) "/home/cweiske/Dokumente/Vorträge/php7/code/dirname-depth.php"
string(43) "/home/cweiske/Dokumente/Vorträge/php7/code"
string(38) "/home/cweiske/Dokumente/Vorträge/php7"
string(1) "/"

func_get_args(), func_get_arg()

Liefert aktuelle Werte, nicht mehr die vom Beginn des Funktionsaufrufs

<?php
function foo($a) {
    $a = 2;
    var_dump(func_get_arg(0));
}
foo(1);
$ php5 code/func_get_args.php
int(1)
$ php7 code/func_get_args.php
int(2)

Ref: php.net: incompatible changes: func_get_args

preg_replace_callback_array()

Neue Funktion: Mehrere Ausdrücke auf einmal ersetzen:

<?php
$a = preg_replace_callback_array(
    array(
        '/a/' => function($match) { return "-c-"; },
        '/c/' => function($match) { return "-a-"; }
    ),
    'abc'
);
var_dump($a);
string(9) "--a--b-a-"

Ref: php.net: preg_replace_callback_array

Funktionsparameter

2 Parameter mit demselben Namen nicht mehr erlaubt:

<?php
function foo($a, $b, $unused, $unused)
{
}
PHP Fatal error:  Redefinition of parameter $unused

& new

Geht nicht mehr:

<?php
$obj = & new stdClass();
PHP Parse error:  syntax error, unexpected 'new' (T_NEW)

War in PHP4 quasi Pflicht, wenn man ordentlich mit Objekten arbeiten wollte.

PHP4-Code wird deshalb nicht mehr funktionieren.

PHP4-Konstruktoren 1/2

Geht noch:

<?php
class A
{
    function A() {}
}

Jetzt __construct nutzen.

PHP-Konstruktoren: BC 2/2

Einfach umbenennen in Bibliotheken geht nicht - bricht BC:

<?php
class A {
    function __construct() {}
}
class B extends A {
    function B() {
        $this->A();
    }
}
new B();
PHP Fatal error:  Call to undefined method B::A()

Statischer Aufruf von nicht statischen Methoden

Deprecated:

<?php
class A
{
    function foo() {}
}
A::foo();
PHP Deprecated:  Non-static method A::foo() should not be called statically

mysql-Extension entfernt

Jetzt muss mysqli / mysqlnd genutzt werden

Ref: php.net: removed extensions in PHP7

Zeitzonenwarnung

Keine Warnung mehr, wenn date.timezone nicht in php.ini gesetzt ist. Standard ist UTC.

$ php5 -r 'ini_set("date.timezone", ""); echo date("c") . "\n";'
PHP Warning:  ini_set(): It is not safe to rely on the
system's timezone settings. You are *required* to use the
date.timezone setting ...
2016-02-25T12:33:40+00:00
$ php7 -r 'ini_set("date.timezone", ""); echo date("c") . "\n";'
2016-02-25T11:33:40+00:00

Extensions

Ref:

Ende