Zwracane typy wartości null w PHP7

159

PHP 7 wprowadza deklaracje typu zwracanego . Oznacza to, że mogę teraz wskazać, że zwracana wartość jest pewną klasą, interfejsem, tablicą, możliwością wywołania lub jednym z nowo wskazanych typów skalarnych, co jest możliwe w przypadku parametrów funkcji.

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

Często zdarza się, że wartość nie zawsze jest obecna i możesz zwrócić coś pewnego typu lub wartość null. Chociaż można ustawić parametry null, ustawiając ich wartość domyślną na null ( DateTime $time = null), nie wydaje się, aby można to zrobić w przypadku typów zwracanych. Czy tak jest w istocie, czy w jakiś sposób nie znajduję, jak to zrobić? Te nie działają:

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

function returnHello(): string|null {
    return 'hello';
}
Jeroen De Dauw
źródło
8
PHP7 nie zezwala jeszcze na typy zwracane wartości null, ale istnieje dokument RFC, który ma na celu rozwiązanie tego problemu w PHP 7.1 tutaj . Proponowana notacja brzmiałaby wówczasfunction returnString(?string $stringNull) : ?string { return $stringNull;}
Elias Van Ootegem
1
Skończyło się na emulowaniu wartości null przez nadużywanie wyjątków w mojej aplikacji. Jeśli nie przeszkadza
Jeroen De Dauw
Być może bardziej sensowne byłoby użycie Trowableinterfejsu PHP7 (a konkretnie rozszerzenie TypeError)
Elias Van Ootegem

Odpowiedzi:

258

PHP 7.1 obsługuje teraz typy zwracane wartości null . Pierwszy dokument RFC, z którym się połączyłem, to ten, do którego się udali:

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

stara odpowiedź:

Ponieważ mój komentarz był właściwie odpowiedzią na pytanie:

PHP 7 nie obsługuje jeszcze zwracanych typów zwracanych wartości null, ale istnieje wyjście RFC , które to rozwiązuje, ma na celu wylądowanie w PHP 7.1. Jeśli się powiedzie, składnia wpłynie na wszystkie wskazówki dotyczące typu (zarówno typy zwracane, jak i wskazówki dotyczące typu):

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

Istnieje również konkurencyjny RFC do dodawania typów związków, które mogłyby zrobić to samo, ale wyglądałyby inaczej:

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

Na razie jednak musisz napisać:

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

Lub po prostu zwróć pusty ciąg, aby był zgodny z zwracanym typem, i sprawdź fałszywą wartość:

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
źródło
5
PHP 7 won't support nullable return-types just yet, but there's an RFC out to address just that- tak, RFC, „jeszcze”. Nie zrozum mnie źle - jestem naprawdę ciężkim użytkownikiem PHP od czasu naprawdę kiepskiego PHP3 do teraz, żadnych luk, ale kiedy zobaczyłem wszystkie te RFC, które odrzucili dla 7, odniosłem wrażenie, że po prostu "WTF ?!". Użytkownicy widzą bałagan i są skłonni posprzątać go w sposób zgodny z poprzednimi wersjami i po prostu otrzymują „nie”. Czyste metody nazewnictwa bałagan? Naprawiono nullbrak bycia zbyt wyjątkowym obywatelem? Nie, nie jest potrzebne. Dodać opcję rozróżniania wielkości liter? Nie… A potem niespodzianka, że ​​ludzie się zmieniają.
Marcin Orłowski
1
@MarcinOrlowski: Wskazówka dotycząca zwracanego typu wartości null miałaby sens. Śledziłem kilka RFC dla 7 i zgodziłem się w większości z odrzuceniem wielu z nich. Zmiany, na których się skupiali, dotyczyły nie tyle języka, co środowiska wykonawczego i kompilatora. W przypadku niektórych odrzuconych specyfikacji RFC warto zapoznać się z wątkami dyskusji, aby zrozumieć, dlaczego zdecydowali się nie wprowadzać tych zmian (np. Wycofali się var). Szkoda, że ​​zamiast tego zaakceptowali zbyt wiele
rzeczy, które warto
@EliasVanOotegem Nullable są teraz poprawnie obsługiwane, ponieważ 7.1 został wydany 1 grudnia.
samotny dzień
@lonesomeday: Rzeczywiście, dodałem link + podstawowy przykład na dole mojej odpowiedzi
Elias Van Ootegem
mmm to dobry typ, aby zaktualizować tę odpowiedź! tj. typ unii nie wydaje się być obsługiwany w PHP 7.1
Dennis
67

Typy dopuszczające wartość null są dostępne w PHP 7.1.

Oto przykład składni:

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

PHP 7.1 jest teraz GA i możesz zaktualizować PHP 7.0 (jest tylko kilka wstecznie niekompatybilnych zmian , które musisz sprawdzić)

nakrętki
źródło
22
IMO dostarczanie deklaracji typu zwracanego bez implementowania wartości nullable jest żartem. Typy zwracane są bezużyteczne, dopóki nie zostanie zaimplementowana funkcja „dopuszczająca wartość null”.
joonas.fi
2
@ joonas.fi Ściśle wpisane wartości zwracane przez IMO powinny zawsze być tego typu. Zwrot zerowy nie dotyczy tego kontraktu i powinien raczej zgłosić wyjątek nadający więcej znaczenia przyczynie wartości null.
Steve Buzonas
8
@SteveBuzonas, jeśli weźmiesz pod uwagę metodę getAgeInYears () na obiekcie reprezentującym osobę, jak możesz modelować osobę, która nie podała nam swojego wieku? Zwrócić null? Zwrócić 0? Zwracanie null semantycznie oznacza „nie wiemy”, a 0 semantycznie oznacza „dana osoba ma 0 lat”. Dlatego uważam, że getAgeInYears ():? Int to najlepszy projekt. Rzucanie wyjątków powinno być zarezerwowane dla dobrze ... wyjątkowych przypadków. Brak znajomości wieku osoby w większości systemów nie powinien być traktowany jako wyjątkowy przypadek.
joonas.fi
@ joonas.fi jest bardzo prawdziwe i jest to powszechna praktyka. Jednak implementacja musi teraz mieć świadomość, że pole może mieć wartość null i jawnie obsługuje odpowiednio. Co bardzo dobrze może być zrobione przez x, chyba że ma wartość null, co równie łatwo można zaimplementować za pomocą try / catch. Ponadto, gdyby faktycznie wymagać wartości w tym polu dopuszczającym wartość null, aby kontynuować wykonywanie, prawdopodobnie lepszym rozwiązaniem jest wyjątek.
Steve Buzonas
Zauważyłem, że ta składnia powoduje, że PHPMD generuje wiele błędów. Miejmy nadzieję, że wkrótce to naprawią.
Tom Jowitt
0

Działa z każdym typem.
Przykład:

public function getOpportunity(): ?Opportunity
{
    return $this->opportunity;
}
Bayma Bruno
źródło