Nullable Rückgabetypen in PHP7

159

PHP 7 führt Rückgabetypdeklarationen ein . Das heißt, ich kann jetzt angeben, dass der Rückgabewert eine bestimmte Klasse, Schnittstelle, ein bestimmtes Array, ein aufrufbarer oder einer der neu anzeigbaren Skalartypen ist, wie dies für Funktionsparameter möglich ist.

function returnHello(): string {
    return 'hello';
}

Oft kommt es vor, dass ein Wert nicht immer vorhanden ist und Sie entweder einen Typ oder null zurückgeben. Während Sie Parameter auf Null setzen können, indem Sie ihren Standardwert auf null ( DateTime $time = null) setzen, scheint es für Rückgabetypen keine Möglichkeit zu geben, dies zu tun. Ist das tatsächlich der Fall oder finde ich irgendwie nicht heraus, wie es geht? Diese funktionieren nicht:

function returnHello(): string? {
    return 'hello';
}

function returnHello(): string|null {
    return 'hello';
}
Jeroen De Dauw
quelle
8
PHP7 lässt noch keine nullbaren Rückgabetypen zu, aber es gibt einen RFC, der dies in PHP 7.1 hier beheben soll . Die vorgeschlagene Notation wäre dannfunction returnString(?string $stringNull) : ?string { return $stringNull;}
Elias Van Ootegem
1
Ich habe die Nullfähigkeit emuliert, indem ich vorerst Ausnahmen in meiner Anwendung missbraucht habe. Wenn Sie auch dumm sind, könnte dies von Nutzen sein: github.com/JeroenDeDauw/OhMyPhp/blob/master/src/…
Jeroen De Dauw
Vielleicht ist es sinnvoller, die PHP7- TrowableSchnittstelle zu verwenden (insbesondere die zu erweitern TypeError)
Elias Van Ootegem

Antworten:

258

PHP 7.1 unterstützt jetzt nullfähige Rückgabetypen . Der erste RFC, mit dem ich verbunden bin, ist der, für den sie sich entschieden haben:

function nullOrString(int $foo) : ?string
{
    return $foo%2 ? "odd" : null;
}

alte Antwort:

Da mein Kommentar eigentlich eine Antwort auf die Frage war:

PHP 7 unterstützt noch keine nullbaren Rückgabetypen, aber es gibt einen RFC , der genau das behebt. Er soll in PHP 7.1 landen. Wenn dies erfolgreich ist, wirkt sich die Syntax auf alle Typhinweise aus (sowohl Rückgabetypen als auch Typhinweise):

public function returnStringOrNull(?array $optionalArray) : ?string
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);//string returned here
    }
    return null;
}

Es gibt auch einen konkurrierenden RFC zum Hinzufügen von Unionstypen, die das Gleiche tun könnten, aber anders aussehen würden:

public function returnStringOrNull(array|null $optionalArray) : string|null
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);//string returned here
    }
    return null;
}

Im Moment müssen Sie jedoch schreiben:

public function returnStringOrNull( array $optionalArray = null)
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);
    }
}

Oder geben Sie einfach eine leere Zeichenfolge zurück, um mit dem Rückgabetyp übereinzustimmen, und überprüfen Sie den falschen Wert:

public function returnStringOrNull( array $optionalArray = null) : string
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);
    }
    return '';
}
//call
$string = $x->returnStringOrNull();
if (!$string) {
    $string = $x->returnStringOrNull(range(1, 10));
}
Elias Van Ootegem
quelle
5
PHP 7 won't support nullable return-types just yet, but there's an RFC out to address just that- Ja, RFC, "gerade noch". Versteh mich nicht falsch - ich bin ein sehr starker PHP-Benutzer seit wirklich beschissenen PHP3-Zeiten bis jetzt, keine Lücken, aber als ich all diese RFCs sah, die sie für 7 abgelehnt haben, war mein Eindruck nur "WTF?!". Benutzer sehen das Durcheinander und sind bereit, es abwärtskompatibel zu bereinigen , und sie erhalten nur "Nein". Saubere Methoden, die Chaos benennen? Behoben, nullnicht zu spezieller Bürger zu sein? Nein, nicht benötigt. Option hinzufügen , um alle Dinge zwischen Groß- und Kleinschreibung zu unterscheiden? Nein. Und dann überraschen Sie, dass die Leute wechseln.
Marcin Orlowski
1
@MarcinOrlowski: Ein nullbarer Rückgabetyp-Hinweis wäre sinnvoll. Ich habe ein paar RFCs für 7 Jahre verfolgt und war größtenteils damit einverstanden, dass sie viele von ihnen ablehnten. Die Änderungen, auf die sie sich konzentrierten, betrafen weniger die Sprache als vielmehr die Laufzeit und den Compiler. Für einige der abgelehnten RFCs lohnt es sich, die Diskussionsthreads durchzulesen, um zu verstehen, warum sie diese Änderungen nicht implementiert haben (z var. B. veraltet ). Was schade ist, dass sie stattdessen eine zu viele nette Sachen akzeptiert haben (zum Beispiel Raumschiffbetreiber)
Elias Van Ootegem
@EliasVanOotegem Nullable-Typen werden jetzt ordnungsgemäß unterstützt, da 7.1 am 1. Dezember veröffentlicht wurde.
einsamer
@lonesomeday: In der Tat, fügte es den Link +
Basisbeispiel
mmm ish ein guter Typ, um diese Antwort zu aktualisieren! dh der Unionstyp scheint in PHP 7.1
Dennis
67

Nullable Typen sind in PHP 7.1 verfügbar.

Dies ist ein Syntaxbeispiel:

public function getName(): ?string
{
    return $this->name; // name can be null
}

PHP 7.1 ist jetzt GA und Sie können ein Upgrade von PHP 7.0 durchführen (es gibt nur wenige rückwärts inkompatible Änderungen , die Sie überprüfen müssen).

die Nüsse
quelle
22
IMO ist es ein Witz, Rückgabetypdeklarationen zu liefern, ohne "nullable" zu implementieren. Rückgabetypen sind unbrauchbar, bis die Funktion "nullable" implementiert ist.
joonas.fi
2
@ joonas.fi IMO streng typisierte Rückgabewerte sollten immer von diesem Typ sein, eine Nullrückgabe gilt nicht für diesen Vertrag und sollte eher eine Ausnahme auslösen, die dem Grund eines Nullwerts mehr Bedeutung verleiht.
Steve Buzonas
8
@SteveBuzonas Wenn Sie eine Methode getAgeInYears () für ein Objekt in Betracht ziehen, das eine Person darstellt, wie würden Sie eine Person modellieren, die uns ihr Alter nicht mitgeteilt hat? Null zurückgeben? 0 zurückgeben? Null semantisch zurückzugeben bedeutet "wir wissen es nicht", während 0 semantisch "die Person ist 0 Jahre alt" bedeutet. Daher würde ich getAgeInYears () :? Int als das beste Design bezeichnen. Das Auslösen von Ausnahmen sollte für Ausnahmefälle reserviert werden. In den meisten Systemen das Alter einer Person nicht zu kennen, sollte nicht als Ausnahmefall angesehen werden.
joonas.fi
@ joonas.fi sehr wahr, und das ist eine gängige Praxis. Ihre Implementierung muss sich jedoch jetzt bewusst sein, dass das Feld nullwertfähig ist und explizit entsprechend behandelt wird. Was sehr gut x sein kann, außer wenn null, was genauso einfach mit einem try / catch implementiert werden könnte. Wenn man tatsächlich einen Wert in diesem nullbaren Feld benötigt, um die Ausführung fortzusetzen, ist eine Ausnahme wahrscheinlich die bessere Option.
Steve Buzonas
Ich habe festgestellt, dass diese Syntax dazu führt, dass PHPMD viele Fehler auslöst. Hoffentlich beheben sie es bald.
Tom Jowitt
0

Es funktioniert mit jedem Typ.
Beispiel:

public function getOpportunity(): ?Opportunity
{
    return $this->opportunity;
}
Bayma Bruno
quelle