Não é possível transmitir argumento nulo ao usar a dica de tipo

193

O código a seguir:

<?php

    class Type {

    }

    function foo(Type $t) {

    }

    foo(null);

?>

falhou no tempo de execução:

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

Por que não é permitido passar nulo como em outros idiomas?

Abdullah
fonte

Respostas:

357

PHP 7.1 ou mais recente (lançado em 2 de dezembro de 2016)

Você pode declarar explicitamente uma variável como nullesta sintaxe

function foo(?Type $t) {
}

isso resultará em

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

Portanto, se você deseja um argumento opcional, pode seguir a convenção, Type $t = nullenquanto que, se precisar fazer um argumento, aceita ambos nulle seu tipo, pode seguir o exemplo acima.

Você pode ler mais aqui .


PHP 7.0 ou mais antigo

Você precisa adicionar um valor padrão como

function foo(Type $t = null) {

}

Dessa forma, você pode transmitir um valor nulo.

Isso está documentado na seção do manual sobre declarações de tipo :

A declaração pode ser feita para aceitar NULLvalores se o valor padrão do parâmetro é definido como NULL.

DonCallisto
fonte
10
Então, por que o objeto nulo não é nulo ?
Pacerier 28/07
4
A maioria dos idiomas permite que nulo tenha qualquer tipo. Neste cenário.
Henry
24
Na minha opinião, este é um construto de linguagem ruim. 1. Em outros idiomas, o null tem a capacidade de ser de qualquer tipo, tornando o null um argumento válido neste caso. 2: Php está usando um valor padrão para um argumento para especificar que nulo é permitido, isso é obscuro e impossibilita um parâmetro obrigatório, mesmo que o desenvolvedor deseje forçar a passagem explícita de um nulo.
Henry
2
Concordo com o @ Henry, além disso, parece estranho ter exigido parâmetros depois do que parece um parâmetro opcional.
Force Hero
6
Concordo com @Henry apenas no 2. Quanto a 1, o fato de você não poder passar nulo function foo(Type $t)é MUITO bom; veja nulos Referências: A Billion Dollar Mistake
Constantin Galbenu
36

A partir do PHP 7.1, tipos anuláveis estão disponíveis, pois os tipos e parâmetros de retorno de função. O tipo ?Tpode ter valores do tipo especificado T, ou null.

Portanto, sua função pode ficar assim:

function foo(?Type $t)
{

}

Assim que você pode trabalhar com o PHP 7.1, essa notação deve ser preferida function foo(Type $t = null), porque ainda força o chamador a especificar explicitamente um argumento para o parâmetro $t.

O operador
fonte
12

Experimentar:

function foo(Type $t = null) {

}

Confira os argumentos da função PHP .

SeanWM
fonte
11
O problema que tenho com isso é que ele altera a definição da função. Agora, o parâmetro é opcional - o que não é realmente o que o autor pretendia (embora, se ele estiver passando nulo, é implicitamente opcional).
esmagar
7

Como outras respostas já mencionadas, isso só é possível se você especificar nullcomo o valor padrão.

Mas a solução mais limpa e orientada a objetos com segurança de tipo seria um 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)';
    }
}

Uso:

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
fonte
1
Essa abordagem geralmente é impraticável, porque agora, em vez de 1 classe, você precisa de 3. Além disso, força o escritor NullFooa substituir métodos abstratos, mesmo que eles não tenham significado (por definição de null).
TheOperator 9/11/16
1
Na minha experiência, o padrão NullObject pode ser prático, se você trabalhar em geral de uma maneira OO clássica muito estrita. Na resposta, imo o padrão NullObject é um pouco abusado, uma vez que se destina especialmente a evitar if (something is null)verificações, pois o NullObject destina-se a cobrir todo o comportamento de um valor inexistente e qualquer colaborador externo não deve estar interessado em saber se um O objeto não existe (nulo) ou não.
perdeu