Un futur vers les retours
On continue dans la série « Ces nouveautés qui rendent heureux » avec l’annonce de la possibilité de forcer des types de retour de fonctions dans PHP 7 ! Cette avancée majeure a fait là encore l’objet de débats assez vifs au sein de la communauté des développeurs PHP, avec des RFC critiquées, d’autres écartées et d’autres qui reviendront un jour ou l’autre d’outre-tombe !
C’est l’histoire d’un type…
Scalaire ou pas, nous pouvons maintenant signifier un type de retour dans les déclarations de nos fonctions, sous la forme suivante :
<MODE D'ACCES> function <NOM> (liste de paramètres) : <TYPE DE RETOUR>
La position de ce type de retour a fait débat d’entrée de jeu, certains développeurs ne souhaitant pas le voir devant le nom de la fonction, comme c’est le cas en C ou Java, pour des raisons de commodité lors des recherches dans le code (chercher « function mafonc » n’aurait plus fonctionné si elle avait du s’appeler « function int mafonc »).
Commençons avec des types non scalaires :
function eleves(): array { return ["jean", "eric", null]; } var_dump(eleves()); /* array(3) { [0]=> string(4) "jean" [1]=> string(4) "eric" [2]=> NULL } */
ou bien encore :
class Eleve { private $_nom; private $_prenom; public function __construct ($nom, $prenom) { $this->_nom = $nom; $this->_prenom = $prenom; } } function eleve($n, $p): Eleve { return new Eleve ($n, $p); } var_dump(eleve("Rack", "Eric")); /* object(Eleve)#1 (2) { ["_nom":"Eleve":private]=> string(4) "Rack" ["_prenom":"Eleve":private]=> string(4) "Eric" } */
Nous avons utilisé dans l’exemple précédent des types non scalaires, respectivement tableau (array) et objet (de la classe Eleve).
Nous pouvons aussi renvoyer des types scalaires, tels que int, float, bool ou encore string :
function qi(): int { return 150; } var_dump(qi());
Si je modifie le type de retour pour essayer les quatre types susnommés, voici ce que j’obtiens :
int(150) bool(true) string(3) "150" float(150)
Pensez à activer le typage strict en faisant figurer en première ligne de votre fichier de test (ou plus proprement, dans l’autoloader de votre application) la directive maintenant bien connue de ceux qui veulent bénéficier des plus récentes fonctionnalités en matière de typage strict, à savoir:
declare(strict_types=1);
Comme toujours, il faut respecter le contrat, sinon gare ! Vous ne pouvez pas écrire :
function quotientintellectuel(): int { return null; }
ou bien encore:
function quotientintellectuel(): int { return "150"; }
Sous peine de courroucer PHP, qui, pour le premier exemple, vous jettera à la figure un joli :
Fatal error: Uncaught TypeError: Return value of quotientintellectuel() must be of the type integer, null returned
Invariance
Elle reste toujours de mise, à savoir que les signatures des méthodes héritées ou implémentées doivent rester EXACTEMENT les mêmes dans les sous-types. Ainsi, si vous écrivez ceci, vous vous provoquerez naturellement l’ire du compilateur :
class Eleve {} interface EleveDao { function trouverParNom($nom): Eleve; } class EleveSqlDao implements EleveDao { function trouverParNom($nom) { // mes plus belles requêtes SQL return new Eleve(); } }
Fatal error: Declaration of EleveSqlDao::trouverParNom($nom) must be compatible with EleveDao::trouverParNom($nom): Eleve
Notez que ce comportement pourrait être modifié dans les versions futures du langage.
Peut-on renvoyer « rien » ?
Il y a eu une tentative d’introduire un type void comme en C/C++ ou Java mais cette proposition a été rejetée. Vous savez que par défaut une fonction PHP renvoie null :
function rien() {} var_dump(rien()); # NULL
Quand on écrit void, on notifie que la fonction ne renvoie rien. Or null par défaut est retourné par PHP, ce sont deux choses différentes.
Avec void on ne renvoie rien, avec return null on renvoie « absence de valeur » !
Quid des fonctions spéciales ?
Certaines fonctions ne sont pas autorisées à faire usage des types de retour :
- les constructeurs
- les destructeurs
- les fonctions de clonage
En tentant de le faire, vous provoqueriez des erreurs fatales.
En résumé
Coluche disait « Voilà une nouvelle qu’elle est bonne ! »; une délicieuse formule qui s’applique à cette nouvelle fonctionnalité qui, avec le typage strict et de nombreuses autres features, constitue une avancée majeure dans le cycle de vie de notre langage préféré. L’introduction de ces possibilités est l’occasion une fois de plus de renforcer la bonne hygiène de vos développements ! Il reste encore des points à régler (void notamment, qu’on espère voir arriver un jour !) mais tout va dans la bonne direction !
N’oublions pas de préciser qu’il faut activer le typage strict pour clairement l’exploiter !
declare(strict_types=1)
Sinon PHP type à sa sauce :p
http://codepad.viper-7.com/uE5H5k
Ouhla, oui, en effet, j’ai oublié de le préciser, ça semble évident lorsqu’on fait usage de ces nouvelles fonctionnalités de typage mais ça ne l’est pas tant que ça, puisque c’est…nouveau ! 🙂 Et oui, c’est parfaitement vrai, si l’on oublie de faire mention de cette directive, PHP « s’arrangera » avec les types comme il l’a toujours fait en effectuant ses conversions de type.
J’ai mis à jour le billet, merci Mathieu, j’avais oublié…mea maxima culpa !
D’après le lien fournis le vote pour le type void est positif, je ne vois pas où il est mentionné que ce type à été abandonné.
Il est clairement indiqué que ce sera disponible pour la version 7.1.0 qui devrait sortir en décembre 2016. L’activité sur le repo GitHub semble aller dans ce sens.
Du coup si vous avez une info allant dans l’autre sens j’en veut bien la source 🙂
– Gecko
C’était le cas lorsque cet article a été écrit (09/10/2015), mais effectivement, le vote (qui a eu lieu du 29/10/2015 au 09/11/2015) s’est fait en faveur du OUI à l’intégration, à une écrasante majorité !