PHP 8 befindet sich bereits im Release-Kandidatenstadium, Version RC 3 wurde am 29. Oktober veröffentlicht und die vollständige Veröffentlichung ist für den 26. November geplant. Es ist also Zeit, einen Blick auf die neuen Funktionen zu werfen, die uns in PHP 8 erwarten. Der Zeitplan für die Veröffentlichung kann hier eingesehen werden . Die offizielle Anleitung zum Aktualisieren auf eine neue Version finden Sie hier .
Unterstützung für Unionstypen ( RFC ) hinzugefügt
Der Vereinigungstyp akzeptiert Werte verschiedener anderer Typen und nicht nur einen.
<?php
declare(strict_types=1);
class Number {
private int|float $number;
public function setNumber(int|float $number): void {
$this->number = $number;
}
public function getNumber(): int|float {
return $this->number;
}
}
/**
* We can pass both floats or integer values
* to the number object. Try passing a string.
*/
$number = new Number();
$number->setNumber(5);
dump($number->getNumber());
$number->setNumber(11.54);
dump($number->getNumber());
exit;
WeakMap ( RFC ) hinzugefügt
Mit schwachen Zuordnungen können Sie Beziehungen zwischen Objekten und beliebigen Werten (sowie SplObjectStorage
) erstellen , während die als Schlüssel verwendeten Objekte nicht vor dem Garbage Collector geschützt sind. Wenn der Sammler ein solches Objekt zerstört, wird es einfach von der Karte entfernt.
Dies ist eine sehr nützliche Funktion. Dadurch können wir noch weniger über Speicherlecks in unserem Code nachdenken. Während dies für die meisten PHP-Entwickler kein Problem sein sollte, lohnt es sich, bei der Erstellung lang laufender Prozesse, beispielsweise mit ReactPHP, darauf zu achten. Mit WeakMaps werden Objektreferenzen automatisch vom Garbage Collector erfasst, wenn das Objekt nicht mehr verfügbar ist.
Wenn Sie dasselbe mit einem Array tun, bleiben die Objektreferenzen bestehen, was zu einem Speicherverlust führt.
<?php
declare(strict_types=1);
class FooBar {
public WeakMap $cache;
public function __construct() {
$this->cache = new WeakMap();
}
public function getSomethingWithCaching(object $obj) {
return $this->cache[$obj] ??= $this->computeSomethingExpensive($obj);
}
public function computeSomethingExpensive(object $obj) {
dump("I got called");
return rand(1, 100);
}
}
$cacheObject = new stdClass;
$obj = new FooBar;
// "I got called" only will be printed once
$obj->getSomethingWithCaching($cacheObject);
$obj->getSomethingWithCaching($cacheObject);
dump(count($obj->cache));
// When unsetting our object, the WeakMap frees up memory
unset($cacheObject);
dump(count($obj->cache));
exit;
Neue Ausnahme ValueError
PHP 8 führt eine neue integrierte Ausnahmeklasse ein
ValueError
. Es ergänzt sich \Exception
. PHP löst diese Ausnahme jedes Mal aus, wenn Sie einen Wert des richtigen Typs an eine Funktion übergeben, sie kann jedoch in dieser Operation nicht verwendet werden. Zuvor wurde in solchen Fällen eine Warnung ausgegeben. Beispiele:
<?php
declare(strict_types=1);
/**
* We pass an array to array_rand,
* which is of the correct type. But
* array_rand expects non-empty arrays.
*
* This throws a ValueError exception.
*/
array_rand([], 0);
/**
* The depth argument for json_decode is a
* valid integer, but it must be greater than 0
*/
json_decode('{}', true, -1);
Beim Definieren von Funktionen können Sie ein variadisches Argument verwenden
Eine beliebige Anzahl von Funktionsparametern kann jetzt durch ein variadisches Argument ersetzt werden, wenn ihre Typen kompatibel sind. Der folgende Code ist beispielsweise falsch:
<?php
declare(strict_types=1);
class A {
public function method(int $many, string $parameters, $here) {
}
}
class B extends A {
public function method(...$everything) {
dd($everything);
}
}
$b = new B();
$b->method('i can be overwritten!');
exit;
Rückgabetyp statisch ( RFC )
Mit dem statischen Rückgabetyp kann jetzt bestimmt werden, ob eine Methode die Klasse zurückgibt, für die die Methode aufgerufen wurde, auch wenn sie vererbt wurde (späte statische Bindung).
<?php
declare(strict_types=1);
class Test {
public function doWhatever(): static {
// Do whatever.
return $this;
}
}
exit;
Objektklassenname Literal ( RFC )
Jetzt können Sie den Klassennamen eines Objekts mit abrufen
$object::class
. Das Ergebnis ist das gleiche wie bei get_class($object)
.
<?php
declare(strict_types=1);
auth()->loginUsingId(1);
dump(auth()->user()::class);
// Or with a temporary variable
$user = auth()->user();
dump($user::class);
exit;
Variable Syntaxeinstellungen ( RFC )
New
und instanceof
kann jetzt mit beliebigen Ausdrücken verwendet werden: new ()(...$args)
und $obj instanceof ()
.
<?php
declare(strict_types=1);
class Foo {}
class Bar {}
$class = new (collect(['Foo', 'Bar'])->random());
dd($class);
exit;
Stringable Interface ( RFC )
PHP 8 führt eine neue Schnittstelle ein
Stringable
, die automatisch hinzugefügt wird, sobald eine Klasse eine Methode implementiert __toString
. Sie müssen diese Schnittstelle nicht explizit implementieren.
<?php
declare(strict_types=1);
class Foo {
public function __toString() {
return 'I am a class';
}
}
$obj = new Foo;
dump($obj instanceof Stringable);
exit;
Merkmale können jetzt abstrakte private Methoden ( RFCs ) definieren.
<?php
declare(strict_types=1);
trait MyTrait {
abstract private function neededByTheTrait(): string;
public function doSomething() {
return strlen($this->neededByTheTrait());
}
}
class TraitUser {
use MyTrait;
// This is allowed:
private function neededByTheTrait(): string { }
// This is forbidden (incorrect return type)
// private function neededByTheTrait(): stdClass { }
// This is forbidden (non-static changed to static)
// private static function neededByTheTrait(): string { }
}
exit;
throw kann jetzt als Ausdruck ( RFC ) verwendet werden
Ausdrücke
throw
können jetzt verwendet werden, wenn nur Ausdrücke zulässig sind: in Pfeilfunktionen Koaleszenzoperatoren, ternäre bedingte Operatoren (ternär / elvis).
<?php
declare(strict_types=1);
$callable = fn() => throw new Exception();
$nullableValue = null;
// $value is non-nullable.
$value = $nullableValue ?? throw new \InvalidArgumentException();
exit;
Optionales hängendes Komma ( RFC ) ist jetzt in Listenparametern zulässig
In Analogie zum hängenden Komma in Arrays können Sie es jetzt in den Listenparametern definieren.
<?php
declare(strict_types=1);
function method_with_many_arguments(
$a,
$b,
$c,
$d,
) {
dump("this is valid syntax");
}
method_with_many_arguments(
1,
2,
3,
4,
);
exit;
Ausnahmen abfangen, ohne in einer Variablen zu speichern ( RFC )
Jetzt können Sie schreiben
catch ()
, um Ausnahmen abzufangen, ohne sie in einer Variablen zu speichern.
<?php
declare(strict_types=1);
$nullableValue = null;
try {
$value = $nullableValue ?? throw new \InvalidArgumentException();
} catch (\InvalidArgumentException) {
dump("Something went wrong");
}
exit;
Unterstützung für gemischten ( RFC ) Typ hinzugefügt
PHP 8 führt einen neuen Typ namens Mixed ein. Es kann den Typen array, bool, callable, int, float, null, object, resource, string entsprechen.
<?php
declare(strict_types=1);
function debug_function(mixed ...$data) {
dump($data);
}
debug_function(1, 'string', []);
exit;
Unterstützung für Attribute hinzugefügt
Es gibt verschiedene Vorschläge zum Implementieren von Attributen in PHP 8:
- https://wiki.php.net/rfc/attributes_v2
- https://wiki.php.net/rfc/attribute_amendments
- https://wiki.php.net/rfc/shorter_attribute_syntax
- https://wiki.php.net/rfc/shorter_attribute_syntax_change
Dies ist eine der größten Änderungen in PHP 8. Es ist möglicherweise zunächst nicht so einfach, dies herauszufinden. Kurz gesagt, mit Attributen können Sie PHP-Funktionen, -Parametern, -Klassen usw. Metadaten hinzufügen. Diese Metadaten können dann programmgesteuert abgerufen werden. Wenn Sie in PHP 7 oder niedriger Doclocks analysieren müssen, können Sie mithilfe von Attributen auf diese Informationen zugreifen, die tief in PHP selbst integriert sind.
Stellen Sie sich zur Verdeutlichung vor, Sie möchten, dass Ihre Benutzer mithilfe eines Attributs Middleware zu einem Klassen- oder Methodencontroller hinzufügen können.
<?php
declare(strict_types=1);
// First, we need to define the attribute. An Attribute itself is just a plain PHP class, that is annotated as an Attribute itself.
#[Attribute]
class ApplyMiddleware
{
public array $middleware = [];
public function __construct(...$middleware) {
$this->middleware = $middleware;
}
}
// This adds the attribute to the MyController class, with the "auth" middleware as an argument.
#[ApplyMiddleware('auth')]
class MyController
{
public function index() {}
}
// We can then retrieve all ApplyMiddleware attributes on our class using reflection
// And read the given middleware arguments.
$reflectionClass = new ReflectionClass(MyController::class);
$attributes = $reflectionClass->getAttributes(ApplyMiddleware::class);
foreach ($attributes as $attribute) {
$middlewareAttribute = $attribute->newInstance();
dump($middlewareAttribute->middleware);
}
exit;
Unterstützung für Weiterleitungskonstruktoreigenschaften ( RFC ) hinzugefügt
Es wird vorgeschlagen, eine einfache Syntax hinzuzufügen, um den Konstruktor mit der Eigenschaftsdefinition zu kombinieren:
<?php
declare(strict_types=1);
class User {
public function __construct(
public int $id,
public string $name,
) {}
}
$user = new User(1, 'Marcel');
dump($user->id);
dump($user->name);
exit;
Unterstützung für den Match-Ausdruck ( RFC ) hinzugefügt
Es wird vorgeschlagen, einen neuen Ausdruck hinzuzufügen
match
, der switch
nur mit sicherer Semantik und der Fähigkeit, Werte zurückzugeben, ähnlich ist.
<?php
declare(strict_types=1);
echo match (1) {
0 => 'Foo',
1 => 'Bar',
2 => 'Baz',
};
exit;
Unterstützung für den nullsafe-Operator (? ->) ( RFC ) hinzugefügt
Wenn das Ergebnis der linken Seite des Operators null ist, wird die Ausführung der gesamten Kette gestoppt und das Ergebnis auf null gesetzt. Ansonsten verhält sich die Kette wie ein normaler Bediener ->
.
<?php
declare(strict_types=1);
class User {
public function getAddress() {}
}
$user = new User();
$country = $user?->getAddress()?->country?->iso_code;
dump($country);
exit;
Unterstützung für benannte Argumente ( RFCs ) hinzugefügt
Mit der Benennung können Sie Argumente an eine Funktion übergeben, die auf dem Namen des Parameters und nicht auf seiner Position basiert. Das heißt, die Werte der Argumente werden selbstdokumentierend, und die Argumente hängen nicht mehr von der Aufzählungsreihenfolge ab, sodass Sie die Standardwerte willkürlich überspringen können.
<?php
declare(strict_types=1);
array_fill(start_index: 0, num: 100, value: 50);
exit;