Impossible de passer un argument nul lors de l'utilisation de l'indication de type

197

Le code suivant:

<?php

    class Type {

    }

    function foo(Type $t) {

    }

    foo(null);

?>

échoué lors de l'exécution:

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

Pourquoi n'est-il pas autorisé à passer null comme d'autres langues?

Abdullah
la source

Réponses:

369

PHP 7.1 ou plus récent (publié le 2 décembre 2016)

Vous pouvez déclarer explicitement une variable nullavec cette syntaxe

function foo(?Type $t) {
}

cela se traduira par

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

Donc, si vous voulez un argument optionnel, vous pouvez suivre la convention Type $t = nulltandis que si vous devez faire en sorte qu'un argument accepte les deux nullet son type, vous pouvez suivre l'exemple ci-dessus.

Vous pouvez en savoir plus ici .


PHP 7.0 ou plus ancien

Vous devez ajouter une valeur par défaut comme

function foo(Type $t = null) {

}

De cette façon, vous pouvez lui passer une valeur nulle.

Ceci est documenté dans la section du manuel sur les déclarations de type :

La déclaration peut être faite pour accepter des NULLvaleurs si la valeur par défaut du paramètre est définie sur NULL.

DonCallisto
la source
10
Alors pourquoi null n'est-il pas l' objet nul ?
Pacerier
4
La plupart des langages permettent à null d'avoir n'importe quel type. Dans ce scénario.
Henry le
24
À mon avis, c'est une construction de langage médiocre. 1. Dans d'autres langues, null a la capacité d'être de n'importe quel type, faisant ainsi de null un argument valide dans ce cas. 2: Php utilise une valeur par défaut pour un argument pour spécifier que null est autorisé, c'est obscur et cela rend un paramètre obligatoire impossible même si le développeur veut forcer un null à être explicitement passé.
Henry
2
Je suis d'accord avec @Henry, en plus il semble bizarre d'avoir des paramètres obligatoires après ce qui ressemble à un paramètre optionnel.
Force Hero
6
Je suis d'accord avec @Henry uniquement sur 2. En ce qui concerne 1, le fait que vous ne pouvez pas passer null à function foo(Type $t)est une TRÈS bonne chose; voir Null References: The Billion Dollar Mistake
Constantin Galbenu
36

À partir de PHP 7.1, les types Nullable sont disponibles, comme les types de retour de fonction et les paramètres. Le type ?Tpeut avoir des valeurs du type spécifié T, ou null.

Ainsi, votre fonction pourrait ressembler à ceci:

function foo(?Type $t)
{

}

Dès que vous pouvez travailler avec PHP 7.1, cette notation doit être préférée function foo(Type $t = null), car elle oblige toujours l'appelant à spécifier explicitement un argument pour le paramètre $t.

L'opérateur
la source
12

Essayer:

function foo(Type $t = null) {

}

Découvrez les arguments de la fonction PHP .

SeanWM
la source
11
Le problème que j'ai avec ceci est que cela change la définition de la fonction. Maintenant, le paramètre est facultatif - ce qui n'est pas vraiment ce que l'auteur voulait (bien que, s'il le passe null, il soit implicitement facultatif).
écraser le
7

Comme d'autres réponses déjà mentionnées, cela n'est possible que si vous spécifiez nullcomme valeur par défaut.

Mais la solution orientée objet de type sécurisé la plus propre serait un 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)';
    }
}

Usage:

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
la source
1
Cette approche est souvent peu pratique, car au lieu d'une classe, vous avez maintenant besoin de 3. De plus, elle oblige l'auteur de NullFooà remplacer les méthodes abstraites, même si elles n'ont pas de sens (par définition de null).
TheOperator
1
D'après mon expérience, le modèle NullObject peut être pratique, si vous travaillez en général d'une manière OO classique très stricte. Dans la réponse, imo le modèle NullObject est un peu abusé, car il est spécialement destiné à éviter les if (something is null)vérifications, car le NullObject est destiné à couvrir tous les comportements d'une valeur inexistante et tout collaborateur extérieur ne devrait pas avoir besoin de se demander si un l'objet est inexistant (nul) ou non.
perdu le