PHP-Versionen

Wie überall in der Software-Entwicklung gibt es auch hier Versionen, die mit der Zeit die „alten“ Funktionalitäten verbessern bzw. neue Funktionalität hinzufügen. Die folgende Liste zeigt einen kurzen Überblick über die wichtigsten Änderungen von PHP 7.1 bis 8.1.

PHP 5.6 und 7.0 wurden hier nicht mehr eingebunden, da diese laut php.net nicht mehr mit Security-Patches versorgt werden und damit auch nicht mehr aktiv verwendet werden sollten. (Stand April 2019)

PHP 8.1

Nativer ENUM Support

Es ist nun möglich (ähnlich wie in anderen modernen Programmiersprachen wie z.b. Kotlin, Rust und Swift) sogenannte ENUMs (kurz für enumerated types) zu erstellen.

Im simpelsten Fall hätten wir z.b. folgendes ENUM

enum TransportMode {
  case Bicycle;
  case Car;
  case Ship;
  case Plane;
  case Feet;
}

und können es wie folgt verwenden:

function travelCost(TransportMode $mode, int $distance): int
{ /* implementation */ } 

$mode = TransportMode::Boat;

$bikeCost = travelCost(TransportMode::Bicycle, 90);
$boatCost = travelCost($mode, 90);

// this one would fail: (Enums are singletons, not scalars)
$failCost = travelCost('Car', 90);

Aber es gibt auch die Möglichkeit den unterschiedlichen ENUM Cases einen skalaren Wert zuzuteilen:

enum Metal: int {
  case Gold = 1932;
  case Silver = 1049;
  case Lead = 1134;
  case Uranium = 1905;
  case Copper = 894;
}

Hier gibt es aber einige Regeln zu beachten:

  • Wenn ein case einen skalaren Wert zugewiesen bekommt müssen ALLE cases einen skalaren Wert erhalten.
  • Skalare Werte müssen (gleich wie der Case selbst) eindeutig sein.
  • Die Skalaren Werte sind read only
  • Um auf den Wert eines ENUM Cases zuzugreifen muss dies über Metal::Gold->value durchgeführt werden

Der never Return Type

Bis jetzt konnte man nie einer Funktion vorgeben, dass sie nichts returnen darf. Es gibt nur den void Return Type dem es aber egal ist ob ein exit ausgeführt wurde oder nicht.

Dies kann nun wie folgt erzwungen werden:

function shutdown(): never {
    exit();
}

Dies kann aber natürlich auch durch einen impliziten Funktionsaufruf passieren wie z.b.:

function redirectToHome(): never {
    redirect('/');
}

Fibers (Non-Blocking/Asynchrones PHP)

Für alle die nicht in die Welt von z.b. NodeJS oder anderen asynchronen Programmiersprachen eingestiegen sind wird dieses Thema etwas eigenartig sein. Prinzipiell wird in PHP der Code synchron ausgeführt. Dies bedeutet, dass der Code in Zeile 2 erst ausgeführt wird wenn der Code in Zeile 1 fertig durchgeführt wurde.

Mit PHP 8.1 wurden Fibers eingeführt um genau dies nun zu ändern und asynchrones PHP zu ermöglichen.

Mit externen Packages wie z.b. amphpReactPHP und Guzzle konnte dies schon in der Vergangenheit erreicht werden jedoch gab es (bis jetzt) keinen definierten Standard dafür.

Für ein gutes Beispiel siehe bitte HIER

Readonly Properties

Es ist nun möglich eine property als readonly zu definieren sodass sie nur 1 mal initialisiert werden darf und danach nicht noch einmal geändert werden darf.

class Release {
    public readonly string $version;
 
    public function __construct(string $version) {
        // Legal initialization.
        $this->version = $version;
    }
}

Was ist nun aber der Unterschied zu Properties mit const?

public readonly string $version; bedeutet, dass unterschiedliche Objekte vom Typ Release unterschiedlich (in sich nicht veränderbare) Werte haben dürfen.

Hingegenpublic const string $version; bedeutet, dass alle Objekte vom Typ Release den gleichen Wert haben müssen.

PHP 8.0

JIT (Just in Time Compiler)

Ohne zu weit ins Detail zu gehen wird mit PHP 8.0 ein JIT Compiler eingeführt der „unter speziellen Bedingungen“ eine bessere Performance bringt. Diese sind aber anscheinend nicht typische CMS wie z.b. WordPress sondern mehr „numerische“ Logik verbessert.

Bild: https://www.php.net/releases/8.0/en.php

Constructor Property Promotion

Bis jetzt mussten Properties beim initialisieren eines Objects wie folgt umgesetzt werden:

class Car {
    public int $wheels;
    public int $doors;

    public function __construct(
        int $wheels = 4,
        int $doors = 5
    ) {
        $this->wheels = $x;
        $this->doors = $y;
    }
}

Dies kann nun aber wesentlich kompakter geschrieben werden:

class Carr {
    public function __construct(
        public int $wheels = 4,
        public int $doors = 5
    ) {}
}

Union Types

Bis jetzt gab es prinzipiell nur den ?Type Union Type um Parameter, Properties oder Return-Types sowohl einen Type zuzuweisen als auch null zu erlauben.

Ansonsten konnten nur über PHPDoc Union Types definiert werden welches wie folgt aussieht


/**
 * @property int|float $power
 */
class Car {
    private $power;

    /**
     * @param int|float $power
     */
    public function setPower($power) {
        $this->power = $power;
    }

    /**
     * @return int|float
     */
    public function getPower() {
        return $this->power;
    }
}

Dies wurde nun in der Hinsicht erweitert, dass mehrere unterschiedliche Typen bei z.b. Properties, Parameters und Return-Types definiert werden dürfen.

class Number {
    private int|float $number;

    public function setNumber(int|float $number): void {
        $this->number = $number;
    }

    public function getNumber(): int|float {
        return $this->number;
    }
}

Prinzipiell wurde bei PHP 8.0 generell mehr auf Typisierung geachtet bzw. werden Typisierungen weiter verstärkt.

Named Attributes

Bis jetzt bestimmte die Position der Parameter innerhalb der Funktionsdefinition wie diese Parameter beim Aufruf angeordnet sein müssen.

function calc($start, $end, $steps) {
    ...
}

Und kann damit nur wie folgt aufgerufen werden:

calc(10, 100, 5);

Nun ist es aber möglich die Funktion wie folgt zu aufzurufen

calc(end: 100, start: 10, steps: 5);

Man darf es aber auch kombinieren um z.b. folgenden Aufruf zu machen:

calc(10, steps: 5, end: 100);

Hier muss aber die Position der nicht benannten Argument korrekt sein!

Nullsafe-Operator

Manchmal möchte man auf ein Object eine Funktion nur dann aufrufen wenn dieses Object auch wirklich vorhanden ist.

$result = null;
if($a !== null) {
    $result = $a->b();
}

Dies kann nun aber auf folgenden Code verkürzt werden:

$result = $a?->b();

Wenn $a null ist, wird die Methode b() nicht aufgerufen und $result wird auf null gesetzt.

Neue String-Vergleich Funktionen

Ich muss regelmäßig String-Operations durchführen um z.b. zu testen ob ein String einen gewissen anderen String beinhaltet, mit diesem startet etc.

Dies konnte bis jetzt nur über die strpos() Funktion durchgeführt werden und musste abhängig von dessen Return Value weitere Logik erst implementiert werden.

Mit PHP 8.0 wurden folgende selbsterklärenden Funktionen eingeführt

  • str_contains( $haystack, $needle )
  • str_starts_with( $haystack, $needle )
  • str_ends_with( $haystack, $needle )

Damit ist es nun wesentlich leichter besser lesbaren Code zu schreiben.

PHP 7.4

Spread-Operator für Arrays

Bei Funktionsaufrufen war der Spread-Operator schon bekannt.

function my_function(...$args) { var_dump($args); }
my_function('test', true, 123);

// Resultat
array(3) {
  [0]=>
  string(4) "test"
  [1]=>
  bool(true)
  [2]=>
  int(123)
}

Dies ist nun auch für Array-Operationen möglich.

$bool_arr = [true, false];
$total_arr = ['text1', 123, ...$bool_arr , 456];
var_dump($total_arr );

// Resultat
array(5) {
  [0]=>
  string(5) "text1"
  [1]=>
  int(123)
  [2]=>
  bool(true)
  [3]=>
  bool(false)
  [4]=>
  int(456)
}

Diese Art von Array Zusammenführung soll ebenso performanter sein als die übliche array_merge() Funktion.

Arrow Funktionen

Ein typischer Fall für Arrow Funktionen wäre z.b. folgendes Beispiel

function cube($n){
	return ($n * $n * $n);
}
$a = [1, 2, 3, 4, 5];
$b = array_map('cube', $a);

Wird zu

$a = [1, 2, 3, 4, 5];
$b = array_map(fn($n) => $n * $n * $n, $a);

Null Coalescing Assignment Operator

Mit PHP 7.0 ist es ja schon möglich einen Fallback Wert zu setzen wenn eine gewissen Variable nicht gesetzt ist.

$this->request->data['comments']['user_id'] = $this->request->data['comments']['user_id'] ?? 'value';

Diese Schreibweise kann nun wie folgt vereinfacht werden

$this->request->data['comments']['user_id'] ??= 'value';

Typisierte Klassen-Argumente

Es ist nun möglich folgende Klassen-Definition

class User {
    /** @var int $id */
    private $id;
    /** @var string $name */
    private $name;
 
    public function __construct(int $id, string $name) {
        $this->id = $id;
        $this->name = $name;
    }
}

wie folgt zu vereinfachen

class User {
    public int $id;
    public string $name;
}

Folgende Typen sind hier erlaubt:

  • bool
  • int
  • float
  • string
  • array
  • object
  • iterable
  • self
  • parent
  • Jegliche/s Klasse oder Interface
  • Nullable Typen (?type)

Jedoch dürfen keine void als auch callable Typen definiert werden!

Preloading

Ohne in komplizierte Details zu gehen bewirkt das OPCache preloading, dass Libraries in den OPCache vorgeladen und damit immer zur Verfügung stehen statt sie bei jedem PHP-Prozess neu zu laden. Dies bewirkt einen deutlichen Performance-Gewinn.

Diese Einstellung muss in der php.ini gesetzt werden.

PHP 7.3

Nachgestelltes Komma in Funktions-Parametern erlaubt

Ab PHP 7.3. ist es nun erlaubt beim letzten Parameter eines Funktionsaufrufs ein Komma hinten anzustellen.

my_function(
    $param1,
    $param2,
);

JSON_THROW_ON_ERROR

Aktuell gibt json_decode() null bei einem Fehler zurück.
null kann aber auch ein gültiges Ergebnis sein was zu Verwirrungen führen kann.

Nun gibt es folgende Funktionen:

  • json_last_error()
    • Gibt (sofern vorhanden) den letzten Fehler zurück, der beim letzten Kodieren/Dekodieren von JSON aufgetreten ist.
  • json_last_error_msg()
    • Gibt bei Erfolg die Fehlermeldung zurück, „No error“, wenn kein Fehler aufgetreten ist. Im Fehlerfall wird FALSE zurückgegeben.

Ein anonymer User hat bei der php.net Definition der json_last_error_msg() Funktion eine nette Helper-Funktion geschrieben, welche die Fehler-Ausgabe bei json_decode() vereinfacht:

<?php
    if (!function_exists('json_last_error_msg')) {
        function json_last_error_msg() {
            static $ERRORS = array(
                JSON_ERROR_NONE => 'No error',
                JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
                JSON_ERROR_STATE_MISMATCH => 'State mismatch (invalid or malformed JSON)',
                JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
                JSON_ERROR_SYNTAX => 'Syntax error',
                JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded'
            );

            $error = json_last_error();
            return isset($ERRORS[$error]) ? $ERRORS[$error] : 'Unknown error';
        }
    }
?>

Alternativ kann dies auch über einen try-catch Block gelöst werden:

try {
    json_decode("{", false, 512, JSON_THROW_ON_ERROR);
}
catch (\JsonException $exception) {
    echo $exception->getMessage(); // echoes "Syntax error"
}

is_countable Funktion

Aktuell ist es für z.b. foreach-Schleifen üblich die Variablen wie folgt zu überprüfen:

$array = [1,2,3,4,5,6,7,8];

if(is_array($array) && sizeof($array) > 0){
  foreach($array as $value){
    
  }
}

Dies kann nun wie folgt verkürzt werden:

$array = [1,2,3,4,5,6,7,8];

if(is_countable($array)){
  foreach($array as $value){
    
  }
}

array_key_first(), array_key_last()

Bis jetzt war es nicht „einfach“ möglich den ersten bzw. letzten „key“ eines Arrays zu erhalten. Mit den Funktionenarray_key_first()und array_key_last() ist dies nun einfach möglich.

PHP 7.2

Native Untersützung für das Bild-Format (BMP)

Bis jetzt musste man bei der Bild-Bearbeitung von BMP-Bildern über PHP externe Bibliotheken verwenden. Jedoch bietet seit PHP 7.2 die GD-Bibliothek die Unterstützung für dieses Bildformat mit an.

Typ „object“ bei Parameter- und Rückgabewerten einstellbar

Bis jetzt war es nicht bei Funktionen als Paramter- oder Rückgabewerte eine Variable vom Typ „object“ anzugeben. Seit PHP 7.2 ist dies nun aber möglich.

function test (object $a): object {

}

exif_read_data() erkennt mehr Daten aus Bildern

EXIF (Exchangeable Image File Format) ist ein Standard für das Abspeichern von Metadaten bei Bild-Dateien.

Bis jetzt waren diese automatisch ausgelesenen Daten aus PHP sehr beschränkt. Jedoch wurden mit PHP 7.2 diverse EXIF-Formate von bekannten Kamera-Herstellern hinzugefügt. Siehe HIER

Verschlüsselte ZIP-Archive nun möglich

Ab PHP 7.2 ist es nun möglich ZIP-Archive mit Passwörtern zu erstellen.

PHP 7.1

„Nullable types“

function test1(?array $a) {
 
}
 
function test2($a): ?array {
 
}

Die erste Funktion (test1) besagt, dass ein Parameter vom Typ „Array“ der Funktion übergeben werden kann, dieser jedoch auch „null“ sein kann (? vor dem array)

Die zweite Funktion (test2) besagt, dass der Rückgabewert der Funktion vom Typ „Array“ sein kann, jedoch aber auch „null“ erlaubt ist.

Ohne diese vorangestellten ? würde bei einem Aufruf der Funktion test1 mit dem Paramter „null“ bzw. bei der Funktion test2 mit dem Rückgabe-Wert „null“ ein „Fatal Error“ produziert werden.

Array und list haben gleiche Funktionalität

Alter Code:

$array = array(0 => 'a', 1 => 'b');
 
list($a, $b) = $array;
 
// $a ist = 'a'
// $b ist = 'b'

Neuer Code:

$array = array(0 => 'a', 1 => 'b', 2 => 'c');
 
[$a, $b] = $array;
 
// $a ist = 'a'
// $b ist = 'b'
 

list(1 => $b, 2 => $c) = $array;
// ist das gleiche wie
[1 => $b, 2 => $c] = $array;

Sichtbarkeiten von Konstanten in Klassen

Wie es schon bei Klassen-Variablen und Funktionen bekannt ist können nun „Sichtbarkeiten“ (bekannt aus der Objektorientierten Programmierung) auch auf Konstanten angewandt werden.

  • public Zugriff auf Variablen ist von überall möglich, d.h. auch von anderen Klassen bzw. Objekten
  • protected Zugriff auf Variablen ist nur in der eigenen Klasse UND von allen Klassen, die von der eigenen Klasse abgeleitet (=extended) wurden, möglich.
  • private Zugriff auf Variablen ist nur in der eigenen Klasse vorhanden.
class test {
    const PUBLIC1 = 'TEST';
 
    public const PUBLIC2 = 'TEST';
    protected const PROTECTED = 'TEST';
    private const PRIVATE = 'TEST';
}

try-catch mit mehreren Exception Angaben möglich

Es ist nun möglich in einem try-catch Block mehrere Exception-Typen mit einem | anzugeben.

try {
     throw new Exception('Fehler');
} catch (Exception | AndererExceptionTyp $catchedException) {
     var_dump($catchedException);
}

mcrypt Erweiterung veraltet => OpenSSL verwenden

Die Funktionen der „mcrypt“ Erweiterung (Funktionsnamen die mit „mcrypt_“ starten) werden nun als „deprecated“ markiert bzw. bei Verwendung in der error.log als „deprecated“ angezeigt.

Ersetzt wird die mcrypt Funktionlität mit den Funktionen aus der OpenSSL Erweiterung.

Sources

Share this post

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

The reCAPTCHA verification period has expired. Please reload the page.