PHP 7 ist da

PHP Logo

Glen Langer

Contao Camp 2016 in Nürnberg

Version: 1.3.0 vom 20.07.2017

(Bild: PHP.net)

Über mich

  • Contao seit 2.5.8
  • PHP ZCE
  • Forum: BugBuster
  • Camp: James Buster, im Auftrag von Contao
  • http://contao.ninja/

Inhalt

  • Umstieg, wann und warum?
  • Neue, zu alte und fast zu alte Funktionen
  • Inkompatibilitäten
  • Migrationshinweise,
    speziell für Contao Erweiterungen
  • Tools

Umstieg, wann und warum?

Umstieg, wann und warum?
http://php.net/supported-versions.php
PHP 7.1 wurde am 02.12.2016 veröffentlicht

Umstieg, wann und warum?

PHP Logo Aus Performance Gründen!

Kern von PHP grundlegend überarbeitet, gegenüber PHP 5.0 soll PHP 7.0 ganze 10-14 mal schneller sein, gegenüber PHP 5.6 immerhin doppelt so schnell und dabei mit geringerem Speicherverbrauch.

Neues

Null coalescing Operator (??)

Spaceship-Operator (<=>)

Array Konstanten

Anonyme Klassen

Exception Handling

Sodium - Neue Krypto-Bibliothek (Libsodium)

Null coalescing Operator (??)

$sortBy = $_GET['sortBy'] ?: 'name';

Problem, wenn "sortBy" nicht gesetzt.
Lösung bisher:

$sortBy = isset($_GET['sortBy']) ? $_GET['sortBy'] : 'name';

Lösung mit PHP 7:

$sortBy = $_GET['sortBy'] ?? 'name';

 

Spaceship-Operator (<=>)

Ein Drei-Wege-Vergleich, vereinfacht Sortierungen.

echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> [];        // 1
echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1

Array Konstanten

Konstanten können nun auch ein Array beinhalten:

define('FARBEN' , ['rot', 'blau', 'grün']);
echo FARBEN[0]; // rot

Anonyme Klassen

interface Logger
{
    public function log($message);
}
 
$echoLogger = new class implements Logger {
    public function log($message)
    {
        echo $message . "\n";
    }
};
 
$echoLogger->log("Hello World!");

Exception Handling

Alle fatalen Fehler sind in PHP 7 Exceptions. Diese können nun abgefangen werden, ohne sofortigen Abbruch des Programms.

Dazu gehört zum Beispiel der ehemals fatale Fehler:
"Call to a member function ?() on a non object".

$foo = null;
$foo->methodCall();

Exception Handling

Laufzeitfehler, genau wie Exceptions, werde nun von einem neuen Interface Throwable abgeleitet.

Diese können nun entweder über dieses Interface oder die Basisklasse Error abgefangen werden.

Achtung: “Error” != “Exception”

$foo = null;
try {
  $foo->methodCall();
} catch (Exception $ex) {
  echo "Fehler: " . $ex->getMessage();
}
// PHP Fatal Error....

Exception Handling

In PHP 7 nun möglich:

$foo = null;
try {
  $foo->methodCall();
} catch (Error $ex) {
  echo "Fehler: " . $ex->getMessage();
}
// Fehler: Call to a member function ...

Exception Handling

Mit catch (Throwable) lassen sich Exceptions und Errors fangen:

$foo = null;
try {
  $foo->methodCall();
} catch (Throwable $ex) {
  echo "Fehler: " . $ex->getMessage();
}
// Fehler: Call to a member function ...

Exception Handling

Variante die kompatibel ist mit PHP 5 und PHP 7:

try {
    // Code that may throw an Exception or Error.
} catch (Throwable $t) {
    // Executed only in PHP 7, will not match in PHP 5.x
} catch (Exception $e) {
    // Executed only in PHP 5.x, will not be reached in PHP 7
}

Removed Extensions

- ext/mssql
- ext/mysql
- ext/sybase_ct
- ext/ereg
- ext/mcrypt (deprecated ab 7.1, ab 7.2 moved to PECL)

Inkompatibilitäten

Inkompatible Features

Skalare Typehints

Uniform variable syntax (Auswertungsreihenfolge)

Änderungen bei 'list'

Änderungen bei 'foreach'

func_get_args()

Skalare Typehints

Vor PHP 7 waren Typehints nur für Objekte und Arrays möglich. Nun auch für primitive Datentypen.

Daher ist es nun nicht mehr möglich, Klassen, Interfaces, Traits wie folgt im Namen zu deklarieren: (case-insensitive)

ab 7.0: bool, int, float, string, null, false, true
ab 7.1: void, iterable
ab 7.2: object

Das betrifft auch die Verwendung der Namen bei class_alias() und use Statements.

Für die Zukunft sind folgende Namen reserviert, erzeugen aber noch keine Fehlermeldung:

resource, mixed, numeric

Skalare Typehints

Auch der Rückgabetyp von Funktionen / Methoden kann nun vorgegeben werden! Komplettes Beispiel:

function addition (int $num1, float $num2, string $text) : string
{
    return $text . ": " . ($num1 + $num2);
}
echo addition(2, 1.14, "Ergebnis");
//Ergebnis: 3.14

Skalare Typehints

Werden die Parameter vom Typ nicht eingehalten, passiert folgendes:

function addition (int $num1, float $num2, string $text) : int
{
    return $text . ": " . ($num1 + $num2);
}
echo addition("2hallo", 1.14, 42);
//PHP Notice: A non well formed numeric value encountered... line 1
//PHP Notice: A non well formed numeric value encountered... line 3
//42

Skalare Typehints

Strengere Prüfung mit strict types, Ausgabe eines Fatal Errors bei Konflikten:

declare(strict_types=1);
function addition (int $num1, float $num2, string $text) : string
{
    return $text . ": " . ($num1 + $num2);
}
echo addition(2, 1.14, 42);
//PHP Fatal error: Uncaught TypeError: Argument 3 ... 
//must be of type string, integer given

Zulässig wäre hier trotzdem ein Integer statt Float zu übergeben, das wird konvertiert.
Hinweis: die "declare" Zeile, die am Anfang einer Datei gesetzt werden kann, muss in jeder Datei enthalten sein, wo die strenge Prüfung gewünscht ist.

Uniform variable syntax (Auswertungsreihenfolge)

Expression PHP 5 interpretation PHP 7 interpretation
$$foo['bar']['baz'] ${$foo['bar']['baz']} ($$foo)['bar']['baz']
$foo->$bar['baz'] $foo->{$bar['baz']} ($foo->$bar)['baz']
$foo->$bar['baz']() $foo->{$bar['baz']}() ($foo->$bar)['baz']()
Foo::$bar['baz']() Foo::{$bar['baz']}() (Foo::$bar)['baz']()

Hint: Use the syntax of the PHP5 interpretation, which is also understood in PHP7.

Änderungen bei 'list'

Bei Verwendung von nur einem Array weist list() in PHP 5 die Werte von rechts beginnend zu. In PHP 7 beginnt list() von links.

//ohne Arrays
$info = array('Kaffee', 'braun', 'Koffein');
list($drink, $color, $power) = $info;
echo "{$drink} - {$color} - {$power}.\n";
//Kaffee - braun - Koffein.

//mit unterschiedlichen Arrays
list($a[], $b[], $c[]) = $info;
echo "$a[0] - $b[0] - $c[0].\n";
//Kaffee - braun - Koffein.

//aber mit dem selben Array
list($a[], $a[], $a[]) = $info;
echo "$a[0] - $a[1] - $a[2].\n";
//PHP 5: Koffein - braun - Kaffee.
//PHP 7: Kaffee - braun - Koffein.

Änderungen bei 'foreach'

Der interne Zeiger innerhalb von foreach im iterierten Array wird nicht mehr modifiziert. Bei zusätzlicher Verwendung der Array-Funktionen current() oder next() innerhalb einer foreach-Schleife, wird sich der entsprechende Code unter PHP 7 anders verhalten.

$array = [0, 1, 2];
      foreach ($array as $key) {
          var_dump(current($array));
          next($array);
}
//PHP 5: int(1), int(2), bool(false)
//PHP 7: int(0), int(1), int(2)

Inkompatibilität: func_get_arg[s]()

PHP 5: func_get_arg() / func_get_args() liefert immer die Originalwerte der Funktionsparameter. Werden die Werte vor dem Aufruf verändert, werden trotzdem die alten Werte geliefert.

PHP 7: Hier würde man die veränderten Werte erhalten.

Inkompatibilität: func_get_arg()

function foo($x) {
    $x++;
    var_dump(func_get_arg(0));
}
foo(1);

Ergibt in PHP 5: 1

Ergibt in PHP 7: 2

Deprecated Features

“PHP 4 Style” Konstruktoren

Nicht-statische Methoden sollten nicht mehr statisch aufgerufen werden

Password hash (salt option)

 

Deprecated Functions

  • __autoload() (ab PHP 7.2)
    • Ersatz ab PHP 5.1 durch spl_autoload_register
  • create_function() (ab PHP 7.2)
    • Ersatz ab PHP 5.3 durch anonyme Funktionen (closures)
  • each() (ab PHP 7.2)
    • Ersatz wäre foreach(), ist auch schneller

Weitere Funktionen sind noch in Diskussion. (Stand: 10.02.2017)

Migrationshinweise

Migrationshinweise für Contao Erweiterungen

Anpassung Abhängigkeiten

Anpassung composer.json bzw. Einstellungen in ER2 auf Contao 3.5.5 bzw. 4.1.0 oder höher.

String Klasse ersetzen

Wurde die String Klasse aus dem Contao Core verwendet?
Dann durch StringUtil ersetzen. Beispiele:

String::toXhtml(...) zu StringUtil::toXhtml(...)

Achtung: Die Methoden der String Klasse wurde vor längerer Zeit statisch. Die StringUtil Klasse verlor dabei die überflüssig gewordene Methode "getInstance".
Erweiterungen mit diesem Aufruf:

$objString = String::getInstance();

müssen da eventuell noch mehr anpassen.
(z.B. die Erweiterung clipboard, siehe #14)

Indirekte Variablen

Wurde ein eigene Hook entwickelt? Der Aufruf der registrierten Klasse und Methode muss angepasst werden.

$this->$callback[0]; zu
$this->{$callback[0]};
$this->$callback[0]->$callback[1](...); zu
$this->{$callback[0]}->{$callback[1]}(...);
System::importStatic($callback[0])->$callback[1](); zu
System::importStatic($callback[0])->{$callback[1]}();

Tools

Tools um die Migration zu vereinfachen von PHP 5 auf PHP 7.

PHP 7 Compatibility Checker (php7cc)

Kommandozeilen-Tool, um die Migration von PHP 5.3-5.6 zu PHP 7 zu vereinfachen. Es sucht nach potenziell problematischen Anweisungen in bestehenden Code und erzeugt Berichte mit Dateinamen, Zeilennummern und kurze Problembeschreibungen.

PHP 7 Compatibility Checker (php7cc)

Ausgabe einer Prüfung:

File: /system/modules/core/library/Contao/String.php
> Line 29: Reserved name "string" used as a class, interface or trait name 
    class String
    {
    }

Aber Achtung: Nicht gefunden wird derzeit so etwas:

$value = \String::encodeEmail($value);
$xhtml = String::toXhtml($html5);

PHP 7 Compatibility Checker (php7cc)

Ausgabe einer Prüfung:

File: /system/modules/core/library/Contao/Database/Mysql.php
> Line 57: Removed function "mysql_connect" called
    mysql_connect($strHost, $dbUser, $dbPass);
> Line 62: Removed function "mysql_query" called
    mysql_query('SET sql_mode=\'\'', $this->resConnection);
...

PHP 7 Compatibility Checker (php7cc)

Ausgabe einer Prüfung:

File: /system/modules/core/modules/ModulePersonalData.php
> Line 90: Indirect variable, property or method access
    $this->{$callback[0]}->{$callback[1]}();

Achtung! Hier wird bereits der korrigierte Quellcode ausgegeben. Die originale Zeile ist:

    $this->$callback[0]->$callback[1]();

PHP 7 Compatibility Checker (php7cc)

Weitere Informationen auf GitHub: sstalle/php7cc

Installationen sind über Composer (global/lokal), als "phar" und als Docker Image möglich.

PHP 7 Migration Assistant Report (MAR)

Kommandozeilen-Tool, um die Migration von PHP 5.4-5.6 zu PHP 7 zu vereinfachen. Es sucht nach potenziell problematischen Anweisungen in bestehenden Code und erzeugt Berichte mit Dateinamen, Zeilennummern und kurze Problembeschreibungen.

PHP 7 Migration Assistant Report (MAR)

Ausgabe einer Prüfung:

Report located at: 
/php7mar/reports/2016-08-18 22.59.28 String.md

Darin im Markdown Format sind Meldungen dieser Art:

critical
/system/modules/core/library/Contao/String.php
* reservedNames
 * Line 25: `class String`

Aber Achtung: Nicht gefunden wird derzeit so etwas:

$value = \String::encodeEmail($value);
$xhtml = String::toXhtml($html5);

PHP 7 Migration Assistant Report (MAR)

Ausgabe einer Prüfung:

Report located at: 
/php7mar/reports/2016-08-18 22.48.29 Mysql.md

Darin im Markdown Format sind Meldungen dieser Art:

critical
/system/modules/core/library/Contao/Database/Mysql.php
* deprecatedFunctions
 * Line 47:	@mysql_connect($strHost, $dbUser, $dbPass);
 * Line 51:	@mysql_query("SET sql_mode=''", $this->resConnection);
...

PHP 7 Migration Assistant Report (MAR)

Ausgabe einer Prüfung:

Report located at: 
/php7mar/reports/2016-08-18 22.33.08 ModulePersonalData.md

Darin im Markdown Format sind Meldungen dieser Art:

critical
/system/modules/core/modules/ModulePersonalData.php
* variableInterpolation
 * Line 72: `		$this->$callback[0]->$callback[1]();`

PHP 7 Migration Assistant Report (MAR)

Weitere Informationen auf GitHub: Alexia/php7mar

Installationen sind über Composer und Download/Clone möglich.

Static analyzer for PHP (Phan)

Phan ist ein statischer Code-Analyzer, von Rasmus Lerdorf ins Leben gerufen, der problematische Code-Stellen aufdeckt. Die Prüfung auf PHP 5 / PHP 7 Kompatibilität ist dabei nur ein kleiner Teil der Tests.

Static analyzer for PHP (Phan)

Ausgabe einer Prüfung: (Contao 3.2.0 in .../core/)

./classes/Ajax.php:155 PhanTypeMismatchArgumentInternal 
Argument 1 (prefix) is int but \uniqid() takes string
./classes/Backend.php:432 PhanTypeMismatchReturn 
Returning type null but getBackendModule() is declared to return string
./library/Contao/Controller.php:794 PhanCompatiblePHP7 
Expression may not be PHP 7 compatible
./library/Contao/User.php:246 PhanCompatiblePHP7 
Expression may not be PHP 7 compatible

Im Vergleich zu den beiden anderen Tools wird bezüglich PHP 7 sehr wenig gefunden, z.B. wurde die Klasse "String" nicht beanstandet.

Static analyzer for PHP (Phan)

Weitere Informationen auf GitHub: etsy/phan

Installationen sind über Composer und Download/Clone möglich.

Achtung: PHan benötigt selbst PHP 7 und die PHP Erweiterung "ast": nikic/php-ast

Linkliste

Informationen zur Migration:

Reporting Tools für die Kommandozeile:

Tutorials:

Danke!

Contao Ninja

 

Aktuelle Version dieser Folien auf: docs.contao.ninja

(auch als PDF und später auch als Video)