Types de retour Nullable en PHP7

159

PHP 7 introduit les déclarations de type de retour . Ce qui signifie que je peux maintenant indiquer que la valeur de retour est une certaine classe, interface, tableau, appelable ou l'un des nouveaux types scalaires, comme cela est possible pour les paramètres de fonction.

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

Il arrive souvent qu'une valeur ne soit pas toujours présente et que vous puissiez renvoyer quelque chose d'un certain type ou null. Bien que vous puissiez rendre les paramètres nullables en définissant leur valeur par défaut sur null ( DateTime $time = null), il ne semble pas y avoir de moyen de le faire pour les types de retour. Est-ce bien le cas ou est-ce que je ne trouve pas comment le faire? Celles-ci ne fonctionnent pas:

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

function returnHello(): string|null {
    return 'hello';
}
Jeroen De Dauw
la source
8
PHP7 n'autorisera pas encore les types de retour nullables, mais il existe une RFC qui vise à résoudre ce problème dans PHP 7.1 ici . La notation proposée serait alorsfunction returnString(?string $stringNull) : ?string { return $stringNull;}
Elias Van Ootegem
1
J'ai fini par émuler la nullité en abusant des exceptions dans mon application pour le moment. Si vous êtes d'accord pour être aussi stupide, cela pourrait être utile: github.com/JeroenDeDauw/OhMyPhp/blob/master/src/…
Jeroen De Dauw
Peut-être qu'il serait plus judicieux d'utiliser l' Trowableinterface PHP7 (en particulier, en étendant le TypeError)
Elias Van Ootegem

Réponses:

258

PHP 7.1 prend désormais en charge les types de retour Nullable . Le premier RFC auquel je me suis lié est celui qu'ils ont choisi:

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

ancienne réponse:

Puisque mon commentaire était en fait une réponse à la question:

PHP 7 ne prend pas encore en charge les types de retour nullables, mais il existe un RFC pour résoudre ce problème, il vise à atterrir dans PHP 7.1. Si elle réussit, la syntaxe affectera alors tous les types-hints (à la fois les types de retour et les types-hints):

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

Il existe également une RFC concurrente pour ajouter des types d'union, qui serait capable de faire la même chose, mais aurait l'air différent:

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

Pour l'instant, cependant, vous devrez écrire:

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

Ou renvoyez simplement une chaîne vide pour être cohérente avec le type de retour et vérifiez la valeur falsifiée:

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
la source
5
PHP 7 won't support nullable return-types just yet, but there's an RFC out to address just that- ouais, RFC, "pour l'instant". Ne vous méprenez pas - je suis un très gros utilisateur de PHP depuis des temps vraiment merdiques de PHP3 jusqu'à maintenant, pas de lacunes, mais quand j'ai vu tous ces RFC qu'ils ont rejetés pour 7, mon impression était juste "WTF?!". Les utilisateurs voient le désordre et sont prêts à le nettoyer de manière rétrocompatible et ils obtiennent simplement "non". Des méthodes propres pour nommer le désordre? Correction de nullne pas être un citoyen trop spécial? Non, pas nécessaire. Ajouter une option pour rendre tous les trucs sensibles à la casse? Nan .. Et puis, surprise que les gens changent.
Marcin Orlowski
1
@MarcinOrlowski: Un indice de type de retour Nullable aurait du sens. J'ai suivi quelques RFC pour 7, et j'ai été d'accord pour la plupart avec eux en rejetant beaucoup d'entre eux. Les changements sur lesquels ils se concentraient n'étaient pas tant sur le langage que sur le moteur d'exécution et le compilateur. Pour certaines des RFC qui ont été refusées, il vaut la peine de lire les fils de discussion pour comprendre pourquoi ils ont choisi de ne pas implémenter ces changements (par exemple, la dépréciation var). Ce qui est dommage, c'est qu'au lieu de cela, ils ont accepté un trop grand nombre de gentils à avoir (opérateur de vaisseau spatial par exemple)
Elias Van Ootegem
@EliasVanOotegem Les types Nullable sont désormais correctement pris en charge, car la version 7.1 est sortie le 1er décembre.
lonesomeday
@lonesomeday: En effet, il le fait, a ajouté le lien + exemple de base au bas de ma réponse
Elias Van Ootegem
mmm ish un bon type pour mettre à jour cette réponse! c'est-à-dire que le type d'union ne semble pas être pris en charge dans PHP 7.1
Dennis
67

Les types Nullable sont disponibles en PHP 7.1.

Voici un exemple de syntaxe:

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

PHP 7.1 est maintenant GA et vous pouvez mettre à niveau à partir de PHP 7.0 (il n'y a que quelques modifications incompatibles avec les versions antérieures que vous devez vérifier)

les noisettes
la source
22
IMO c'est une blague de fournir des déclarations de type de retour sans implémenter "nullable". Les types de retour sont inutilisables jusqu'à ce que la fonctionnalité «nullable» soit implémentée.
joonas.fi
2
@ joonas.fi Les valeurs de retour IMO strictement typées doivent toujours être de ce type, un retour nul ne tient pas à ce contrat et devrait plutôt lever une exception donnant plus de sens à la raison d'une valeur nulle.
Steve Buzonas
8
@SteveBuzonas si vous considérez une méthode getAgeInYears () sur un objet représentant une Personne, comment modéliseriez-vous une personne qui ne nous a pas dit son âge? Renvoyer null? Retourne 0? Renvoyer null signifie sémantiquement "nous ne savons pas", tandis que 0 signifie sémantiquement "la personne a 0 ans". Par conséquent, je dirais que getAgeInYears ():? Int est le meilleur design. Les exceptions devraient être réservées à des cas bien ... exceptionnels. Le fait de ne pas connaître l'âge d'une personne dans la plupart des systèmes ne doit pas être considéré comme un cas exceptionnel.
joonas.fi
@ joonas.fi est très vrai, et c'est une pratique courante. Cependant, votre implémentation doit maintenant être consciente que le champ est nullable et qu'il est explicitement géré en conséquence. Ce qui peut très bien être do x sauf lorsque null qui pourrait tout aussi bien être implémenté avec un try / catch. De plus, si l'on devait réellement exiger une valeur dans ce champ Nullable pour continuer l'exécution, une exception est probablement une meilleure option.
Steve Buzonas
J'ai remarqué que cette syntaxe fait que PHPMD génère beaucoup d'erreurs. J'espère qu'ils le répareront bientôt.
Tom Jowitt
0

Cela fonctionne avec n'importe quel type.
Exemple:

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