Neues PHP Release pünktlich im Zeitplan erschienen

PHP 7.4 veröffentlicht: Der Guide zu den neuen Features
Keine Kommentare

Während die PHP-Community auf das für September 2021 geplante Major Release von PHP 8 wartet, geht es erst einmal mit einem bemerkenswerten Release von PHP 7.4 weiter. Nico Anastasio blickt auf die neuen Features von PHP 7.4, die heute offiziell freigegeben wurden.

Wie immer, wenn der Winter kommt – schon einige Jahre hintereinander (ich hätte nicht gedacht, dass ich das irgendwann mal sage) – bringt er eine neue PHP Version mit sich. Während wir alle auf das für September 2021 geplante Major Release von PHP 8 und seine langersehnten Features warten, und vor allem auf die Aufnahme von JiT, wurde jetzt erst einmal PHP 7.4 offiziell freigegeben.

Das Ziel von PHP 7.4 ist, die Geschwindigkeit und die Leistung Ihres Codes zu verbessern sowie die Lesbarkeit zu erhöhen. Es bringt eine Menge neuer Features und Funktionen mit, kommt zugleich aber auch mit mehreren Deprecations und ein paar Inkompatibilitäten, um die Sie sich kümmern müssen, wenn Sie auf die neue Version migrieren wollen.

Wir haben eine Menge zu erledigen, also lasst uns gleich zur Sache kommen.

Was ist neu in PHP 7.4 und warum sollten Sie sich darum kümmern?

Typed Properties werden nun unterstützt

Eines der am häufigsten kommentierten Features des RFC war es, die Eigenschaften einer Klasse eingeben zu können (die Abstimmung erzielte ein erstaunliche Ergebnis von 70 positiven zu 1 negativen Stimmen)

Type Hinting bei Methoden gibt es schon eine Weile, und wir alle wissen, warum es eine gute Praxis ist, sie anzuwenden. Jetzt begeben wir uns auf die nächste Stufe. Type Properties bestehen darin, dass wir mehrere Arten von Variablen für unsere Parameter definieren können.

Die jetzt unterstützten Typed Properties sind:

  • bool
  • int
  • float
  • string
  • array
  • object
  • Iterable
  • Self
  • Parent
  • sowie type classes’ name
  • und interfaces name
  • nullable type (durch Eingabe eines questing mark vor dem type)

Wenn Sie nicht alle oder einige der gerade erwähnten Wörter kennen, würde ich Ihnen empfehlen, einen Blick in diesen Beitrag über die Grundlagen von PHP zu werfen.

Achtung: Es ist nicht möglich, eine Variable vom Typ void einzugeben. Der Grund dafür ist, dass sie nicht variable sind. Außerdem hat es eine Syntax, die leicht misszuverstehen ist und der Type callable sein Verhalten je nach Kontext ändert. Wir können auch statische Properties zuweisen, indem wir den Typ zwischen dem Keyword static und dem Namen der Variablen einfügen.

Alle Beispiele in den folgenden Abschnitten sind gültig und können verwendet werden.

 
class User {
    // declaring scalar
    private int $id;
    public string $name;
    // declaring iterable
    public iterable $iterables;
    // desclaring classes and  interfaces
    protected ClassName $classType;
    // desclaring variable with default value
    public string $name = "Nico";
    // desclaring variable with nullable value
    public ?string $void = null;
    // desclaring more variable of same time at once
    public float $x, $y;
    // desclaring using keyword var
    var bool $flag
}

Für den Fall, dass Sie ein Property deklarieren und sie dann einen anderen Type verwenden, werden Sie einen Fehler erhalten: Uncaught TypeError.

Spread Operator

Mit 43 positiven Stimmen zu einer, wurde ein weiteres beliebtes Feature Teil dieses Releases. Der Spread Operator, auch Argument Unpacking genannt. Um die Wahrheit zu sagen, dieses Feature ist seit PHP 5.6 verfügbar, ist aber nur dafür reserviert, wenn es um eine Liste von Argumenten einer Funktion geht.

Der Spread Operator hat mehr oder weniger den gleichen Zweck wie die Funktion array_merge(), aber da es sich hier um ein PHP-Kernkonstrukt und nicht um eine Funktion handelt, ist die Verbesserung der Geschwindigkeit und der Speicherleistung recht beeindruckend.

Lassen Sie uns mit der Synax beginnen. Sie können den Spread Operator verwenden, indem Sie drei Punkte vor einen Array oder vor einer Traversable Instance voranstellen, einschließlich der Funktion generator.

 
$mammals = ['bear', 'ape'];
$animals = ['owl', 'crocodile', ...$mammals, 'frog'];
array(5) {
    [0]=>
    string(3) "owl"
    [1]=>
    string(9) "crocodile"
    [2]=>
    string(4) "bear"
    [3]=>
    string(9) "ape"
    [4]=>
    string(4) "frog"
}

Einfach, oder?

Wie können diesen Operator ebenfalls nutzen, um Arrays um andere Arrays zu erweitern, die auf die gleiche Weise gebildet wurden.

 
$mammals = ['bear', 'ape'];
$animals = ['owl', 'crocodile', ...$mammals, 'frog'];
$domain = [...$animals, …$fungus, …$plant];

Ich glaube, dass der Spread Operator das Beste aus sich herausholen wird, wenn er neben Funktionen oder ähnlichen Generatoren eingesetzt wird.

 
function getMammals(){
    return ['bear', 'ape'];
}
$animals = [...getMammals(), 'owl', 'crocodile'];
 
function generateFungus() {
    $fungus = ['porcino', 'portobello'];
    yield $fungus;
}
$domain = ['bear', 'ape', 'pine', 'lettuce', ...generateFungus()];

Die Kernentwickler von PHP haben eine erstaunliche Arbeit geleistet und erlauben es uns nun, weniger Code zu schreiben und die Lesbarkeit unserer Skripte zu verbessern.

Pfeilfunktionen

Um ganz ehrlich zu sein, glaube ich, dass die anonymen Funktionen nicht das beste Feature von PHP ist. Aber ich bewundere die Mühe, die sich das Kernteam gemacht hat, um PHP zu verbessern. Mit 51 Stimmen gegen 8 Stimmen wird es einige Syntaxänderungen an diesem besonderen Merkmal der Sprache geben. Lassen Sie uns damit beginnen, einen Blick darauf zu werfen, wie es vor PHP 7.4 funktioniert hat:

 
$mammals = ['bear', 'ape'];
$animals = function($animals) use($mammals){
    return array_merge($animals, $mammals);
};

Eine Pfeilfunktion kann Variablen erben, die mit dem Keyword use übergeben werden, wie im Codebeispiel angezeigt. Das ist eine recht komplizierte Art, Parameter zu übergeben, und für jemanden, der dieses Keyword zum ersten Mal sieht, kann es ziemlich verwirrend sein.

Ein weiteres Beispiel ist die Verwendung von Array-Funktionen wie array_map() oder array_filter(). Wenn Sie nicht wissen, was diese Funktionen tun, können Sie dies im Beitrag „PHP array functions (exposed)“ nachlesen.

In diesem Fall würden Sie so etwas wie das hier machen:

 
function counterize($domains) {
    return count($domains);
}
$domains = ['bear', 'ape', 'pine', 'lettuce','porcino', 'portobello'];
$plurals = array_map('counterize, $domains);

Sie rufen die Counterize-Funktion mit dem ersten Parameter von array_map() auf und übergeben ein Element.

Mit den Pfeilfunktionen können Sie diesen Code in einer Teile refaktorisieren (eigentlich müssen Sie es in einer Zeile machen, da Sie ihn nicht für mehrere verwenden können).

Außerdem muss für den Anfang das Keyword fn benutzt werden.

 
$domain = ['bear', 'ape', 'pine', 'lettuce','porcino', 'portobello'];
$plurals = array_map(fn($domains) => count($domains), $domains);

Es gibt viel Raum für Verfeinerungen bei diesem Feature, aber die gute Nachricht ist, dass es sich bereits stark verbessert hat. Zum Beispielen brauchen Sie jetzt das Keyword use nicht mehr verwenden, wenn Sie eine Variable übergeben wollen. Außerdem können Sie auch anonyme Funktionen in Methoden innerhalb einer Klasse verwenden werden und Sie können $this-Variablen darin verwenden, wie Sie es bei anderen Methoden tun.

Null Coalescing Assignment Operator

Das hier ist die kleine Kirsche auf der Sahnetorte. PHP 7 hatte zwei Operatoren freigegeben, die ich auch persönlich gerne benutze. Einer ist der Spaceship Operator und der andere der Null Coalescing Operator. Zwei kleine Dinge, die meinen Code lesbarer machen.

Jetzt gehen wir einen Schritt weiter zum Null Coalescing Operator. Lassen Sie uns so tun, als müssten Sie einen Wert einer Variablen entsprechend eines Query Strings zuweisen.

$animal = (isset($_GET['animal'])) ? $_GET['animal'] : 'none';

Ein einfacher Ternary Operator: Wenn sich der String animal innerhalb der superglobalen Variable $_GET befindet, weist der Code aus dem vorherigen Beispiel den Wert der Variablen $animal zu, andernfalls wird die variable zu none.

Lassen Sie es uns nun entsprechend PHP 7 und aufwärts verbessern:

$animal = $_GET['animal'] ?? 'none';

Viel besser, oder?

Stellen Sie sich nun vor, dass die übergebene Variable „gesprächiger“ wäre:

$this->request->data['theAnimalSpecieThatIsTheKingOfTheSavanna'] = $this->request->data['theAnimalSpecieThatIsTheKingOfTheSavanna'] ?? 'none';

Jetzt sieht der Schnipsel nicht mehr so toll aus. Daher die Einführung eines neuen Operators: Der Null Coalescing Assignment Operator. Wir können denselben Code nun umschreiben indem wir Folgendes eingeben:

$this->request->data['theAnimalSpecieThatIsTheKingOfTheSavanna'] ??= 'none';

Wenn die Variable vor dem Operator gesetzt wird, erhalten wir diese, andernfalls setzen wir die Variable als none.

Covariant Returns und Contravariant Parameter

In der Information sind Abweichungen Eigenschaften, die einige Operatoren und Types charakterisieren. Es gibt drei Arten von Abweichungen:

  • Invariant, wenn der übergeordnete Type den Type des Subtypes einschränkt
  • Kovariant, wenn er die Subtypebeziehung bewahrt
  • kontravariant, wenn er sie umkehrt

Sie werden sehen, dass (aber für ein paar Ausnahmen) PHP invariante Parameter- und Return Types hat. Als ich von diesem Konzept erfuhr, war es fast unmöglich, online gute Beispiele zu finden. Also werde ich versuchen, es hier so einfach wie möglich zu machen.

Class Animal {}
Class Mammals extends Animal {}
 
Class Factory {
    public function make() :Animal {}
}
 
Class ChildFactory {
    public function make() :Mammals {}
}

Das vorherige Beispiel ist solide, da die ChildFactory eine Gruppe von Säugetieren erstellt, die Animal ist. Zu beachten ist, dass wir auch nicht gegen Liskov’s SOLID Prinzip verstoßen.

Class Animal {}
Class Mammals extends Animal {}
 
Class Factory {
    public function use(Mammals): {}
}
 
Class ChildFactory {
    public function make(Animal) {}
}

Hier haben wir etwas Ähnliches, aber umgekehrt. Die Main Factory akzeptiert etwas bestimmtes anstatt dass die Child-Methode einen breiteren Paramter akzeptiert. Dies wird als kontravarianter Parametertyp bezeichnet und ist nun in PHP 7.4 erlaubt. Ich muss zugeben, dass ich noch nie ein Beispiel aus der Praxis gesehen habe und ich prognostizieren, dass es sowieso selten verwendet werden wird.

Weak References

Die Weak Reference gibt es schon seit einigen Jahren und ist tatsächlich eine gängige Praxis in Programmiersprachen wie C#, Java und Python. In PHP jedoch ist es jedoch ein neues Konzept und wenn man ein Neuling ist, wird es eine Herausforderung sein, diese zu verstehen.

Was sind Weak References?

Das PHP-Handbuch beschreibt Weak References als eine Möglichkeit, eine Referenz zu einem Objekt aufrecht zu erhalten, ohne das Objekt dabei zu zerstören. Was ist damit gemeint? Schauen wir uns einmal die Syntax an, dann werden wir sehen, warum wir damit arbeiten sollten:

$animal = new Animal;
$weakreference = WeakReference::create($animal);
var_dump($weakreference->get());
unset($obj);
var_dump($weakreference->get());
object(Animal)#1 (0) {
}
NULL

Wenn wir zum ersten Mal die Variable anzeigen, dann sehen wir das Objekt. Wir sehen das Objekt ein zweites Mal, doch behält man immer noch die Referenz, selbst wenn der zurückgegebene Wert gleich Null ist. Die Syntax ist sehr einfach, jetzt ist lediglich zu klären, wann und warum man eigentlich damit arbeiten sollte. Und die Antwort darauf ist: Sporadisch.

Ich bin mir sehr sicher, dass 98 Prozent unser Applikationen niemals dieses Feature benötigen werden, zumindest nicht vorläufig. Man wird es allerdings in einigen bestimmten Fällen brauchen, wenn man einige Daten hat, die in einem Cache abgerufen wurden und die Möglichkeit besteht, dass man die Daten nicht immer wieder neu abrufen will. Falls man mehr Speicher benötigt, dann kann man einige der Werte, die man im Moment nicht braucht, wieder zurücksetzen, sie durch einige relevante Daten ersetzen, die man möglicherweise sofort benötigt, um dann die alten wiederherzustellen. Das kann man machen, indem man die Referenz (oder in diesem Fall, die Weak Referece) der Daten behält, die man wiederherstellen will. Die Vorteile bestehen darin, dass man viel Speicherverbrauch einspart und dementsprechend Leistung hat.

Die Nachteile, meiner Meinung nach, sind die, dass dieses Feature momentan noch nicht vollständig entwickelt zu sein scheint (zumindest in PHP 7.4) und wir noch ein paar weitere Versionen von PHP benötigen werden, damit es verfeinert wird.

Preloading

In diesem neuen Feature gibt es viel zu besprechen. Wir sprechen hier über den PHP Lifecycle. Das Preloading besteht aus dem Verfahren des Ladens von Bibliotheken oder Frameworks in das, dass man als OPCache bezeichnet. Das Ziel ist es, die Leistung der PHP Engine zu verbessern und das macht man, indem man das Skript auf der Festplatte speichert.

Es kann mit einem Beispiel aus dem Sport verglichen werden, wenn ein Spieler seine Muskeln aufwärmt, bevor er auf das Spielfeld geht und von Anfang an bereit ist und reagieren kann, während er sich hingegen steif fühlen würde und nicht schnell bewegen könnte, wenn er für lange Zeit auf der Bank geblieben wäre. Ich weiß, dass euch das Wort OPCache aufgefallen ist und ihr euch fragt, was es damit auf sich hat. Hier ist eine schnelle Erklärung dazu: OPCache kümmert sich um unsere PHP-Quelldateien, kompiliert sie in „Opcodes“ und speichert diese ausgearbeiteten Dateien auf der Festplatte. OPCodes sind eine niedrigstufige Repräsentation unseres Codes. Dadurch vermeidet das OPCache, den Übersetzungsvorgang unserer Quelldateien zum Code hin, der zur Laufzeit ausgeführt werden muss. Von hier aus geht es zur verbesserten Leistung.

Das Preloading wird von einer Direktive in der php.ini kontrolliert, die opcache.preload heißt. Es spezifiziert das PHP-Skript, dass bei Serverstart kompiliert werden muss. Hier ist der Haken an der Sache: Wenn das OPCache eine Direktive verwendet, um die Dateien vorzuladen und beim Start unseres Servers schneller verfügbar zu machen, dann hat die Bearbeitung dieser Dateien keinen Effekt, da die Datei bereits gespeichert wurde. Das ergibt Sinn, oder?

Um dieses Problem zu lösen und um die Modifikation effizienter zu machen, müssen man den Server neustarten. Das ist ein ärgerlicher Nachteil, wenn man eine Applikation hat, die bereits in einer Produktionsumgebung ist.

Neuer Custom-Object-Serialization-Mechanismus

Das ist ein weiteres Feature, das von Nikita Popov vorgeschlagen wurde und mit 20 zu 7 Stimmen durchgekommen ist. Wenn man derzeit ein Objekt serialisieren will, dann hat man drei Möglichkeiten:

  • Die __sleep() magic-Method
  • Die __wakeup() magic-Methoden
  • Und das Serialisierungs-Interface

Hier kann man mehr über die magic-Methoden in OOP erfahren und hier kann man tiefer in das objektorientierte Interface eintauchen.
Nikita Popov sagt, dass alle Optionen hier Probleme haben und der Code, den sie brauchen, um das Ergebnis zu erhalten, nicht zuverlässig ist und zu verschiedenen Problemen führen kann.
Um diese Hindernisse zu lösen, werden wir nun zwei brandneue spezifische magic-Methoden haben; zum einen die serialize()-Methode, die ein Array zurückgibt, und die unserialize()-Methode, die ein Array benötigt, um damit zu beginnen.
Falls ihr eine API entwickelt, dann könnt ihr das als Geschenk ansehen!

// Returns array containing all the necessary state of the object.
public function __serialize(): array;
// Restores the object state from the given data array.
public function __unserialize(array $data): void;

Foreign Function Interface oder kurz: FFI

Entweder hält man dies für das Beste, was PHP jemals widerfahren ist, oder man hält es für etwas, dass man niemals einsetzen wird und macht sich die Mühe, es direkt nach Schließen dieses Artikeln zu vergessen. FFI ist eine Erweiterung, die es ermöglicht, Bibliotheken zu laden, die C-Funktionen aufrufen oder auf C-Datenstrukturen in PHP zugreifen. Das Gute daran ist, dass man keine Zwischensprache lernen muss, um FFI zu verwenden, es wird mehrere statische Methoden geben, die Aktionen auf den C-Daten durchführen. Wie das Handbuch besagt, befindet sich FFI nicht nur in einer experimentellen Phase, es wird sogar als gefährlich eingestuft, diese Klasse arbeitet mit einer sehr niedrigstufigen Sprache und man muss in der Lage sein, C zu verwenden, um damit zu arbeiten.

Hier ist ein Beispiel für den Code, den man schreiben wird:

// create an FFI object using the static method, load the standard C library (libc) and eventually export the text with the  function printf()
$ffi = FFI::cdef(
    "int printf(const char *format, ...);",
    "libc.so.6");
// call C's printf()
$ffi->printf("Hello %s!\n", "world");
// Hello world!

Wenn man C liebt und bereit ist, seine PHP-Skripte durch die Verwendung einer niedrigstufigen Sprache zu verbessern, kann man das jetzt tun. Wie dem auch sein mag, man kann anmerken, dass dieses FFI-API mit der ffi.enable-Direkte in der php.ini eingeschränkt werden kann, um das Risiko zu senken.

Numeric Literal Separator

Dies ist nur ein kleines Feature, um die Lesbarkeit unseres Codes zu verbessern. In PHP 7.4 ist es nun erlaubt, Unterstriche zur Trennung von Zahlen zu verwenden.

6.674_083e-11; // float
299_792_458; // decimal
0xCAFE_F00D; // hexadecimal
0b0101_1111; // binary

Man kann es für eine Anwendung verwenden, die Kreditkarten benutzen oder mit Binärzahlen arbeitet, die Unterstriche werden von der PHP-Engine ignoriert.

Reflection für Referenzen

Bis PHP 7.3 sind Bibliotheken und Frameworks, die Dumping- und Vergleichsoperationen durchgeführt haben, gezwungen, einen Roundabout zu benutzen, um Referenzen zu erkennen. Ein bekanntes Beispiel ist VarCloner, ein Bestandteil von Symfonys Debug, das komplizierte Ansätze verwendet, um die Referenz von einzigartigen Cookies zu erkennen. Nikita Popov schlug die Klasse ReflectionReference vor, um dies zu lösen. Sie bietet die Funktionalität von spl_object_hash(), aber für Referenzen anstelle von Objekten.

Das ist die eigentliche Klasse.

final class ReflectionReference {
    /* Returns ReflectionReference if array element is a reference, null otherwise. */
    public static function fromArrayElement(array $array, int|string $key): ?ReflectionReference;
    /* Returns unique identifier for the reference. The return value format is unspecified. */
    public function getId(): int|string;
    private function __construct(); // Always throws
    private function __clone(); // Always throws
}

Dies ist ein viel sauberer Weg, um die Referenzen zu erhalten, besonders jetzt, da wir in PHP 7.4 typisierte Variablen haben.

mb_str_split

Hier gibt es eine weitere kleinere Verbesserung. Die Funktion str_split() ist erstmals in PHP 5 angekommen und ihr Scope ist die Konvertierung eines Strings in ein Array.
Hier ist die volle Spezifikation:

str_split ( string $string [, int $split_length = 1 ] ) : array

Wie man sehen kann, akzeptiert es einen String als ersten Parameter und ein Integer als zweite Option, die die maximale Länge des Chunks angibt.
Hier ist ein Beispiel:

print_r(str_split("mammals"));
Array ( [0] => m [1] => a [2] => m [3] => m [4] => a [5] => l [6] => s )

mb_str_split() macht dasselbe, aber wie alle anderen mb_*-Funktionen arbeitet es auf Codepunkten und nicht auf Bytes.

Password Hashing Registry

Dieses Feature wurde von Sara Golemon vorgeschlagen. Ihr Vorschlag sucht nach einer Lösung für ein Problem auf Linux-Distributionen, bei denen php-src schlank gehalten wird, wobei zusätzliche Erweiterungen in separaten Paketen bereitgestellt werden. Sie schlug einen Password-Hashing-Registry-Mechanismus vor, der dem der php_hash_register_algo() API der Hash-Erweiterung ähnelt. Das Ergebnis ist die neue PHP-Funktion password_algos(), die ein Array mit der vollständigen Liste aller registrierten Password-Hashing-Algorithmen zurückgibt. Der Wert dieses Arrays wird die menschliche Hash-Identity sein, die ohnehin nicht dem menschenlesbaren Namen für den Algorithmus entsprechen könnte.

Hier ist ein Beispiel für die Funktion:

print_r(password_algos());
Array (
      [0] => "2y" // Ident for "bcrypt"
      [1] => "argon2i"
      [2] => "argon2id"
  )

Fazit des ersten Teils

Wie im letzten Jahr sieht es so aus, dass wir auch in diesem Winter wieder viele Geschenke von den Entwicklern bekommen werden, die im Kernteam von PHP arbeiten. Dies ist keine Breaking-Change-Version, aber es wird als Grundlage für das verwendet, was PHP 8 im Jahr 2020 sein wird. Es gibt viele neue interessante Features, die gelernt werden müssen, um die Sprache in ihrer Gesamtheit zu nutzen, und einige von ihnen, wie Type Variablen, die Covariant Returns und Contravariant Parameters werden bleiben und sich im Laufe der Zeit verbessern. Wenn man PHP beherrschen will, muss man es lernen und wer glaubt, dass er diese Sprache bereits beherrscht, sollte das noch einmal überdenken.

Was kann man als nächstes machen? Man muss wissen, was in PHP 7.3 steckt, um PHP 7.4 vollständig zu verstehen.

Dieser Artikel erschien zuerst im Englischen, geschrieben von Nico Anastasio auf anastsionico.uk.

Eine Ausführliche Auflistung aller neuen Funktionen von PHP 7.4 ist in den Release Notes zu finden. PHP 7.4 steht auf der PHP-Seite zum Download bereit.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -