Nie można przekazać argumentu o wartości null podczas korzystania z podpowiedzi typu

197

Poniższy kod:

<?php

    class Type {

    }

    function foo(Type $t) {

    }

    foo(null);

?>

nie powiodło się w czasie wykonywania:

PHP Fatal error:  Argument 1 passed to foo() must not be null

Dlaczego nie można przekazać null, tak jak w innych językach?

Abdullah
źródło

Odpowiedzi:

369

PHP 7.1 lub nowszy (wydany 2 grudnia 2016 r.)

Możesz jawnie zadeklarować zmienną, która ma mieć nulltaką składnię

function foo(?Type $t) {
}

spowoduje to

$this->foo(new Type()); // ok
$this->foo(null); // ok
$this->foo(); // error

Tak więc, jeśli chcesz opcjonalnego argumentu, możesz postępować zgodnie z konwencją, Type $t = nullpodczas gdy jeśli chcesz, aby argument akceptował oba nulli jego typ, możesz postępować zgodnie z powyższym przykładem.

Możesz przeczytać więcej tutaj .


PHP 7.0 lub starszy

Musisz dodać wartość domyślną, taką jak

function foo(Type $t = null) {

}

W ten sposób możesz przekazać mu wartość null.

Jest to udokumentowane w sekcji podręcznika dotyczącej deklaracji typu :

Deklaracja może akceptować NULLwartości, jeśli domyślna wartość parametru jest ustawiona na NULL.

DonCallisto
źródło
10
Więc dlaczego nie jest pusty obiekt zerowy ?
Pacerier,
4
W większości języków null może mieć dowolny typ. W tym scenariuszu.
Henry
24
Moim zdaniem jest to kiepska konstrukcja językowa. 1. W innych językach null może być dowolnego typu, dzięki czemu w tym przypadku wartość null jest ważnym argumentem. 2: Php używa domyślnej wartości dla argumentu, aby określić, że dopuszczalna jest wartość null, jest to niejasne i uniemożliwia wprowadzenie obowiązkowego parametru, nawet jeśli programista chce wymusić jawne przekazanie wartości null.
Henry
2
Zgadzam się z @Henry, ponadto dziwnie wygląda to, że wymagane parametry są po tym, co wygląda jak opcjonalny parametr.
Force Hero
6
Zgadzam się z @Henry tylko na 2. Jeśli chodzi o 1, fakt, że nie możesz przekazać null do, function foo(Type $t)jest BARDZO dobrą rzeczą; patrz Odniesienia
zerowe
36

Począwszy od PHP 7.1 dostępne są typy dopuszczające wartość null , zarówno jako typy zwracane przez funkcje, jak i parametry. Typ ?Tmoże mieć wartości określonego Type Tlub null.

Twoja funkcja mogłaby więc wyglądać tak:

function foo(?Type $t)
{

}

Jak tylko będziesz mógł pracować z PHP 7.1, ta notacja powinna być preferowana function foo(Type $t = null), ponieważ nadal zmusza wywołującego do jawnego określenia argumentu dla parametru $t.

TheOperator
źródło
12

Próbować:

function foo(Type $t = null) {

}

Sprawdź argumenty funkcji PHP .

SeanWM
źródło
11
Problem, który mam z tym polega na tym, że zmienia definicję funkcji. Teraz parametr jest opcjonalny - co nie jest tak naprawdę tym, co zamierzał autor (chociaż jeśli przekazuje go jako null, jest on niejawnie opcjonalny).
zmiażdżyć
7

Jak już wspomniały inne odpowiedzi, jest to możliwe tylko wtedy, gdy określisz nulljako wartość domyślną.

Ale najczystszym zorientowanym obiektowo rozwiązaniem bezpiecznym dla typów byłby NullObject :

interface FooInterface
{
    function bar();
}
class Foo implements FooInterface
{
    public function bar()
    {
        return 'i am an object';
    }
}
class NullFoo implements FooInterface
{
    public function bar()
    {
        return 'i am null (but you still can use my interface)';
    }
}

Stosowanie:

function bar_my_foo(FooInterface $foo)
{
    if ($foo instanceof NullFoo) {
        // special handling of null values may go here
    }
    echo $foo->bar();
}

bar_my_foo(new NullFoo);
Fabian Schmengler
źródło
1
Takie podejście jest często niepraktyczne, ponieważ zamiast 1 klasy potrzebujesz teraz 3. Ponadto zmusza autora NullFoodo zastąpienia metod abstrakcyjnych, nawet jeśli nie mają one znaczenia (z definicji null).
TheOperator
1
Z mojego doświadczenia wynika, że ​​wzorzec NullObject może być praktyczny, jeśli ogólnie pracujesz w bardzo ścisły, klasyczny sposób OO. W odpowiedzi, imo wzorzec NullObject jest nieco nadużywany, ponieważ ma na celu szczególnie uniknięcie if (something is null)kontroli, ponieważ NullObject ma obejmować wszystkie zachowania nieistniejącej wartości i żaden zewnętrzny współpracownik nie powinien być zainteresowany tym, czy obiekt nie istnieje (null) lub nie.
przegrał