
Glen Langer
Contao Camp 2016 in Nürnberg
Version: 1.3.0 vom 20.07.2017
(Bild: PHP.net)
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.
Null coalescing Operator (??)
Spaceship-Operator (<=>)
Array Konstanten
Anonyme Klassen
Exception Handling
Sodium - Neue Krypto-Bibliothek (Libsodium)
$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';
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
Konstanten können nun auch ein Array beinhalten:
define('FARBEN' , ['rot', 'blau', 'grün']);
echo FARBEN[0]; // rot
interface Logger
{
public function log($message);
}
$echoLogger = new class implements Logger {
public function log($message)
{
echo $message . "\n";
}
};
$echoLogger->log("Hello World!");
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();
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....
In PHP 7 nun möglich:
$foo = null;
try {
$foo->methodCall();
} catch (Error $ex) {
echo "Fehler: " . $ex->getMessage();
}
// Fehler: Call to a member function ...
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 ...
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
}
- ext/mssql
- ext/mysql
- ext/sybase_ct
- ext/ereg
- ext/mcrypt (deprecated ab 7.1, ab 7.2 moved to PECL)
Inkompatible Features
Skalare Typehints
Uniform variable syntax (Auswertungsreihenfolge)
Änderungen bei 'list'
Änderungen bei 'foreach'
func_get_args()
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
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
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
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.
| 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.
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.
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)
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.
function foo($x) {
$x++;
var_dump(func_get_arg(0));
}
foo(1);
Ergibt in PHP 5: 1
Ergibt in PHP 7: 2
“PHP 4 Style” Konstruktoren
Nicht-statische Methoden sollten nicht mehr statisch aufgerufen werden
Password hash (salt option)
__autoload() (ab PHP 7.2)Weitere Funktionen sind noch in Diskussion. (Stand: 10.02.2017)
Migrationshinweise für Contao Erweiterungen
Anpassung composer.json bzw. Einstellungen in ER2 auf Contao 3.5.5 bzw. 4.1.0 oder höher.
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)
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 um die Migration zu vereinfachen von PHP 5 auf PHP 7.
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.
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);
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);
...
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]();
Weitere Informationen auf GitHub: sstalle/php7cc
Installationen sind über Composer (global/lokal), als "phar" und als Docker Image möglich.
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.
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);
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);
...
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]();`
Weitere Informationen auf GitHub: Alexia/php7mar
Installationen sind über Composer und Download/Clone möglich.
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.
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.
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
Informationen zur Migration:
Reporting Tools für die Kommandozeile:
Tutorials: