Des réunions sans ordinateur ni téléphone ? C'est possible !

31 mars 2015 agile, réunion, travail

Qui n’a jamais eu l’occasion de voir un conférencier faisant face à une armée de laptops ouverts, en se demandant si l’audience lui prêtait réellement attention1 ?

Qui n’a jamais vécu la situation suivante, lors d’une réunion ?

— Tu peux répêter la question ?
(intérieurement) Forcément, tu avais plus l’air plus absorbé par ton téléphone que par ce qui se disait…
— Bien sûr, je demandais si …

Ou encore, qui n’a jamais pris le temps de lire un mail alors qu’une collègue présentait le résultat de plusieurs jours de travail ? Voire même d’y répondre2 ? Ratant au passage une partie du message ou du raisonnement suivi ?

J’ai été dans les trois situations : j’ai déjà arrêté de prêter attention pendant quelques secondes à une personne qui prenait le temps de me présenter un sujet, j’ai déjà été dans une salle pleine en ayant le sentiment que le conférencier parlait dans le vide, et j’ai déjà eu envie de faire remarquer qu’il n’était pas très correct de faire répêter alors qu’on n’écoutait pas quelques instants plus tôt.

Un de mes profs d’IUT considérait qu’à partir du moment où un étudiant était devant un PC, il n’écoutait plus aussi attentivement… En fait, il n’avait peut-être pas tord : je sais que moi-même, avec un écran devant moi, ai tendance à le regarder de temps en temps !


Par conséquent, pour éviter de faire aux autres ce que je n’aime pas qu’on me fasse, je tâche désormais de ne prendre mon PC portable pour aller en réunion qu’aussi peu souvent que possible : uniquement si j’ai quelque chose à projeter (et je le ferme quand j’ai terminé) ou lorsqu’il s’agit d’une réunion pendant laquelle je vais réllement en avoir besoin (pour coder, par exemple).

Dans la même logique, je ne garde mon téléphone avec moi que si j’attends un appel qu’il ne faut impérativement pas que je rate — et je ne regarde pas mes mails ni mes SMS / hangouts dessus3. La majorité du temps, il reste posé à côté de mon ordinateur, loin de la salle de réunion : comme pour les mails, il est rare qu’un appel ne puisse attendre une heure ou deux !


Au bureau, un collègue et moi essayons depuis peu de pousser cette pratique en avant — en commençant par les démos de fin de sprint, puisqu’il s’agit de la réunion organisée par l’équipe technique (dont nous faisons tous deux partie) à laquelle l’ensemble de nos collègues sont invités.

Nous sommes en effet convaincu que certaines réunions peuvent être plus efficaces et plus courtes si les participants prêtent toute leur attention au sujet du jour ; quitte à ne pas venir et à se consacrer pleinement à une autre tâche s’ils estiment ne pas y avoir leur place.

Lors de notre avant-dernière démo il y a quelques semaines4, nous avons annoncé à l’oral que nous souhaitions que chacun vienne sans portable5. En fin de semaine dernière, nous avons été un peu plus loin, en scotchant l’affiche suivante à l’entrée de la salle de réunion6 :

Une démo de fin de sprint ?

Bien sûr, en échange, nous avons également fait quelques efforts de notre côté, pour que le temps investi par chacun soit rentabilisé au mieux.

En particulier, nous avons ces derniers mois progressé sur la préparation et la forme de nos démos :

  • nous les faisons désormais systématiquement à deux, de manière à ce qu’un développeur parle, debout, en regardant son public, pendant que l’autre manipule pour lui le PC qui sert à démontrer le travail effectué (et nous échangeons les rôles en milieu de démo),
  • chacun des deux démonstrateurs passe deux à trois heures, la veille, à préparer son texte et ce qu’il souhaite montrer,
  • et ils effectuent une répétition orale le matin même, pour adapter les derniers détails (il n’est pas rare de se rendre compte, en parlant, que certains éléments ne sont pas aussi clairs qu’ils pourraient l’être) et s’assurer que tout est prêt (cas d’exemples, navigateurs déjà ouverts avec les bons onglets, …)

Le résultat est une démo de fin de sprint qui est plus rythmée, qui dure moins longtemps (une vingtaine de minutes, contre une grosse demi-heure il y a quelques mois) et suite à laquelle les questions sont mieux ciblées : tout le monde y gagne !


Pour faciliter un peu la transition, encourager tout le monde à jouer le jeu et aussi donner un aspect plus festif à la démo de fin de sprint, une approche sympa peut être celle-ci, qui complète l’affiche reproduite plus haut7 :

Quelques viennoiseries !

Nous avons pour la première fois demandé de venir à notre démo sans portable il y a trois semaines ; une majeure partie de l’équipe a joué le jeu. Et la semaine dernière, pour la seconde fois ? Aucun ordinateur8 ni téléphone dans la salle pendant les 20 minutes de démo !


  1. Et ce que la conférence soit intéressante ou non ! 

  2. Après tout, un mail, c’est forcément urgent et ça ne peut jamais attendre une heure ! #sarcasm 

  3. Pour éviter la distraction de la diode qui clignote, une approche est de poser le téléphone écran contre la table — ou de le garder dans la poche. En n’activant le vibreur que pour les appels téléphoniques et en le désactivant pour toutes les autres notifications ;-) 

  4. Notre équipe bosse en Scrum, avec des sprints de trois semaines. 

  5. Notez l’emploi du terme portable, volontairement ambigu, qui pouvait signifier aussi bien ordinateur portable que téléphone portable

  6. La formulation ne se veut volontairement pas trop sérieuse : le but n’est pas de repprocher quoi que ce soit à qui que ce soit ! 

  7. À pas loin de 25€ de viennoiseries toutes les trois semaines, cette approche n’est malheureusement pas tellement jouable sur le long terme ;-( 

  8. sauf celui du présentateur, bien sûr — qui attend de toute façon la fin de sa démonstration pour prendre une viennoiserie ; difficile de parler, sinon ^^ 

PHP 7 et processus d'évolution de PHP : slides de ma présentation à l'AperoPHP lyonnais du 25 février

3 mars 2015 slides, php, php-7, afup, aperophp, internals@

Toutes les fin de mois1, l’antenne lyonnaise de l’AFUP organise un ApéroPHP :

Les apéros PHP sont ouverts à tous, quelque soit le niveau, le but est de rencontrer d’autres développeurs PHP de la région lyonnaise,
de boire un verre ensemble, de discuter de tout et de rien, en fonction des envies de tout le monde.

Lors de l’Apéro du 25 février 2015, j’ai eu l’occasion de donner une présentation, où j’ai parlé des nouveautés apportées par PHP 7, la prochaine version majeure de notre langage de prédilection, ainsi que du processus d’évolution de PHP, notamment à travers la mailing-list internals@.

Les slides que j’ai utilisés comme support sont disponibles en ligne2 : PHP 7 et processus d’évolution de PHP : slides de ma présentation à l’AperoPHP lyonnais du 25 février.



  1. En théorie, les ApéroPHP lyonnais ont lieu le 29 de chaque mois. En pratique, la date varie un peu, mais c’est généralement vers la fin du mois. Rendez-vous sur aperophp.net, ou suivez l’AFUP Lyon sur Twitter : @AFUP_lyon

  2. Pour ceux qui voudraient plus d’informations que les slides en eux-même, j’ai noté quelques points dans les notes du présentateur, accessibles via la touche s

Ce mois-ci sur internals@php - Janvier 2015

23 février 2015 php, internals@

This post should be available in English in a few days.


1468 messages ont échangés en janvier 2015 sur la mailing-list internals@ de PHP, soit quasiment le double des mois précédents — et d’ailleurs plus que tous les mois depuis que j’ai commencé à effectuer ces dépilages1 ! Voici donc un mois riche en événements, avec beaucoup d’activité autour de PHP 7 !

Sous forme d’un graphique représentant le nombre de mails par mois sur les trois dernières années, on obtient :


Pour commencer, les votes se sont terminés sur la RFC: PHP 5.7 qui proposait la sortie d’une version 5.7 de PHP qui aurait allongé le support de la branche 5.x et ajouté des avertissements sur les fonctionnalités qui disparaîtront avec l’arrivée de PHP 7. Avec 14 votes “pour” et 19 votes “contre”, elle a été rejetée et nous ne verrons donc pas de version 5.7 de PHP. Bien sûr, si PHP 7 venait à introduire des changements plus importants que ceux actuellement prévus, il sera possible de re-discuter de cette proposition.

François Laupretre a profité de ce fil de discussion pour souligner qu’il était important, pour encourager les développeurs à monter de version, d’inclure des fonctionnalités attirantes dans PHP 7.0, sans attendre 7.1 ou 7.2 qui ne bénéficieront pas de la même exposition. Même chose pour des améliorations orientées sécurité, d’ailleurs.

Rowan Collins a quant à lui souligné qu’il était peu probable de devoir attendre 10 ans pour PHP 8 et que les dix ans entre PHP 5.0 et PHP 7.0 n’ont vu que peu de versions mineures sur leur première moitié — contrairement à ce qui se fait depuis PHP 5.4. Un cycle d’une version majeure tous les cinq ans lui semblerait plus réaliste.


Julien Pauli a indiqué qu’il serait intéressant que les extensions PECL les plus utilisées soient compatibles avec PHP 7 avant la sortie de la première version RC.

En parallèle, Rasmus Lerdorf a donné du travail aux lecteurs de la mailing-list : prendre une application, n’importe laquelle, et la tester sous PHP 7 (en comparant avec PHP 5.6), en vue d’identifier les changements de comportements et bugs qui pourraient faire obstacle à une montée de version pour les utilisateurs finaux. Comme l’a souligné Sebastian Bergmann, c’est encore plus facile pour de nombreux frameworks et bibliothèques, pour lesquels une bonne première étape est de jouer leur suite de tests automatisés. Pour faciliter les choses, Rasmus Lerdorf a fourni une box Vagrant PHP 7.

Plusieurs ont répondu présent et ont identifié plusieurs problèmes dans différentes applications, qui ont été signalés en vue de corrections, soit du côté des applications, soit du côté de PHP, selon les cas. Dan Ackroyd a quant à lui indiqué que l’extension imagick fonctionnait, maintenant, sur PHP 7.

Rasmus Lerdorf a remarqué un changement de comportement suite à une petite optimisation effectuée il y a quelques temps sur les fonctions de tri utilisées par des fonctions comme usort(). Alexey Zakhlestin a en conséquence suggéré qu’il pourrait être intéressant de lever un avertissement E_STRICT si une fonction de comparaison de ce type ne retourne pas une valeur entière — ce qui est incorrect. Le même type de changement a également été remarqué par Pascal Chevrel sur une autre application.


En tout début de mois, Nikita Popov a ouvert les votes sur la RFC: Remove deprecated functionality in PHP 7, qui proposait de supprimer de PHP 7 les fonctionnalités qui étaient marquées comme obsolètes depuis quelques temps. Une fois les votes terminés, l’ensemble des points proposés sont à supprimer et ne devraient donc plus exister pour PHP 7.

Un peu plus tard, Anatol Belski a relancé la discussion autour de la RFC: Removal of dead or not yet PHP7 ported SAPIs and extensions, qui proposait de supprimer de PHP 7 un ensemble de vieilles SAPIs et d’extensions qui semblaient ne plus être maintenues ou reposer sur des bibliothèques qui ne le sont plus elles-mêmes. Dmitry Stogov a souligné qu’il restait quelques extensions qui n’avaient pas encore été converties ou adaptées pour PHP 7. Après avoir été contactés hors-liste, quelques mainteneurs se sont manifestés pour indiquer qu’ils allaient adapter leurs extensions.


Toute fin décembre et en réponse à des demandes exprimées depuis longtemps, Andrea Faulds a rédigé la RFC: Scalar Type Hints, qui proposait d’étendre le mécanisme de type-hints de PHP aux types de données scalaires : entiers, flottants, booléens et chaînes de caractères.

Adam Harvey a rapidement souligné qu’il serait intéressant de lever des avertissements dès PHP 5.72 en cas d’utilisation des mots-clefs correspondant dans des contextes (noms de classes) où cet usage ne serait plus possible avec PHP 7, d’autant plus que certains frameworks incluent des classes de ces noms.

Même s’il s’agit plus de déclarations de types que de type-hints, plusieurs ont indiqué que cette proposition était intéressante et qu’il s’agissait probablement d’une bonne façon de faire, pour ce qui est des type-hints scalaires, en retenant un principe de typage souple.

Toutefois, la première version de cette RFC ne supportait qu’un typage souple, et d’autres voix se sont élevées pour indiquer que privilégier un typage strict serait préférable, ou que les conversions implicites de types n’étaient pas souhaitables. Comme l’a souligné Marcio Almada, la bataille du typage souple ou strict n’est pas nouvelle — peut-être qu’une idée serait de permettre les deux3, avec une syntaxe différente ? Éventuellement, via une autre RFC ?

Suite à ces échanges, en milieu de mois, une version 0.2 de la RFC a été publiée, proposant à la fois un mode de typage souple et un mode de typage strict, configuré par fichier appelant — puisque permettre à chaque fonction de choisir entre l’un ou l’autre serait risqué — ce qui faciliterait également la migration vers du code plus strict.

Robert Stoll a rapidement proposé que l’instruction declare() correspondante pourrait n’être valide qu’en début de fichier, pour lever toute ambiguité et éviter d’avoir des fichiers qui utilisent potentiellement plusieurs modes de typage. D’autres voix se sont exprimées pour souligner qu’avoir deux modes de typage ou les configurer à l’appel n’était pas une bonne approche — même s’il est à noter qu’une fonction recevra systématiquement le type de donnée qu’elle attend. Au final, comme à chaque fois que les sujets du typage et des type-hints scalaires reviennent sur internals@, les avis sont plutôt partagés, avec des opinions fortes et tranchées et de longs débats… et probablement plusieurs personnes réagissant avant d’avoir réellement compris l’intégralité de la proposition.

À propos, si vous souhaitez en savoir plus sur ce que propose cette RFC, j’ai publié sur ce blog, il y a deux semaines, un article intitulé en faveur de la RFC “Scalar Type Hints”.

Les débats se sont calmés après quelques jours assez intenses, mais je n’ai aucun doute sur le fait qu’ils reprendront de plus belle si cette RFC va jusqu’à l’étape de votes !


Au tout début du mois, Levi Morrison a annoncé que les votes allaient bientôt être ré-ouverts sur la RFC: Return Type Declarations — et ils l’ont effectivement été quelques jours plus tard. Cette proposition permettrait de déclarer une fonction (ou méthode) devant retourner un instance d’une classe données de la manière suivante :

function ma_fonction_01($un_param) : DateTime
{
    return new DateTime( ... );
}

Cette RFC a finalement été acceptée pour PHP 7, avec 47 votes pour et 3 votes contre !


Andrea Faulds a relancé la RFC: Combined Comparison (Spaceship) Operator, qui avait été initialisée par Davey Shafik il y a quelques temps. L’idée semble intéressante, mais comme l’a souligné Jordi Boggiano, il serait peut-être bon d’utiliser un nom un peu moins marrant que T_SPACESHIP — qui serait toutefois un nom fréquemment utilisé dans d’autres langages.

En réponse, Nikita Popov a indiqué qu’une fonction, pouvant être passée comme callback, pourrait être plus intéressante qu’un opérateur, ce à quoi il a été répondu qu’un opérateur comme <=> resterait cohérent avec les autres opérateurs de comparaison et n’entraînerait pas de conflit de nom avec une fonction utilisateur.

La mise en place d’un opérateur ayant le même fonctionnement mais en comparaison stricte n’est pas à l’ordre du jour — mais l’idée pourrait revenir sur le tapis dans le futur ;-)


Juan Basso a rédigé la RFC: Preserve Fractional Part in JSON encode, qui visait initialement à modifier json_encode() pour préserver la partie décimale valant 0 des nombres flottants lors de leur encodage en JSON — par exemple, 10.0 serait encodé vers 10.0 et plus vers 10 comme c’est le cas aujourd’hui (les deux possibilités étant valides d’après la norme JSON). Stas Malyshev a répondu que ceci pourrait être fait dès PHP 5.6 via l’ajout d’une option non-activée par défaut, l’activation par défaut pouvant éventuellement venir plus tard.

Les votes ont été ouvert sur cette RFC quelques jours plus tard et elle a été acceptée avec 14 votes “pour” et 0 vote “contre”. Il est à noter que cette modification arrivera sur PHP 5.6.x, ce qui est théoriquement possible pour des fonctionnalités bien ciblées.


Dans une discussion autour de la RFC: Remove PHP 4 Constructors, Matteo Beccati a annoncé qu’il avait commencé à travailler sur un patch à php-cs-fixer qui aiderait lors de migrations de PHP 5.x vers PHP 7.

En revenant au sujet de cette RFC en elle-même, Andrea Faulds a indiqué qu’elle entraînerait une grosse cassure de compatibilité et qu’il vaudrait peut-être mieux se limiter, au moins pour l’instant, à un avertissement lors de l’emploi de constructeurs façon PHP 4. Et comme Florian Margaine l’a souligné, il serait bien que même des applications qui ne sont plus activement développées aujourd’hui fonctionnent sans mal sur PHP 7. Et même si les constructeurs façon PHP 4 ne sont plus mis en avant depuis la sortie de PHP 5, ils n’ont jamais été officiellement marqués comme obsolètes.

Quoi qu’il en soit, avoir deux manières de définir un constructeur, ne se comportant pas toujours de la même façon, n’est pas appréciable !


Benjamin Eberlei a rédigé la RFC: Add PHP files to auto_prepend from extensions, dont l’idée première était de permettre à des extensions PHP (développées en C, donc) de définir des scripts PHP qui seraient exécutés au début de chaque requête service PHP — suite à quoi il deviendrait possible de développer une partie de ces extensions directement en PHP plutôt qu’en C. Cela reviendrait à standardiser quelque chose que plusieurs extensions font aujourd’hui chacune un peu à leur façon.

Sara Golemon a répondu qu’il pourrait être intéressant d’implémenter la notion de fonctions/classes/constantes persistantes, qui éviteraient de recharger du code à chaque requête (ce qui a un coût, même en cas d’utilisation d’un cache d’opcodes).

Une approche pourrait également être d’inclure le code PHP en question directement dans l’extension, au lieu de dépendre de fichiers PHP externes (qui devraient alors être placés au bon endroit, ce qui peut être source d’erreurs). Celle-ci resterait alors composée d’un seul élément, contenant lui-même du code C compilé et du code PHP ne faisant qu’un pour l’utilisateur. En parallèle, Pierre Joye a souligné que le déploiement de fichiers PHP liés à une extension pourrait être géré par l’outil pickle ou directement par les distributions.

Je suis curieux de voir comment les choses évolueront (d’autant plus quelques patchs ont été écrits), considérant qu’il y a ici plusieurs idées : faciliter le développement d’extensions en permettant l’utilisation de PHP au lieu de C pour certaines composantes soit internes à l’extension soit exposées à l’utilisateur, ou bien permettre l’écriture de liens entre code en espace-utilisateur et les fonctionnalités de l’extension. Benjamin Eberlei a d’ailleurs clarifié l’objectif qu’il avait avec cette RFC.

Une refonte de l’API d’extensions étant en cours de réflexion côté HHVM, Sara Golemon a noté qu’il pourrait être intéressant d’arriver à quelque chose de commun entre HHVM et PHP à ce niveau — ce qui permettrait aux extensions qui ne sont pas fortement liées aux moteur de PHP (une majorité d’extensions, a priori) d’être compatibles avec HHVM et vice-versa. Toutefois, Stas Malyshev a souligné qu’il fallait définir clairement les objectifs d’une telle proposition, afin de déterminer si elle fonctionnerait effectivement avec tant d’extensions que cela.


En tout début de mois et après avoir adapté le patch correspondant pour PHP 7, Stas Malyshev a relancé le sujet de la RFC: Skipping optional parameters for functions, qui vise à permettre de sauter des paramètres lors d’appels de fonctions — paramètres qui prendraient alors leur valeur par défaut. Rowan Collins a souligné que l’idée allait plus loin que ne pas savoir quelles sont les valeurs par défaut : il s’agit aussi de ne pas se soucier d’une éventuelle évolution de ces valeurs par défaut.

Nikita Popov a rédigé la RFC: Remove hex support in numeric strings, qui faisait remarquer qu’il était parfois possible d’utiliser des nombres hexadécimaux dans des chaînes de caractères, mais seulement dans certains cas — la correction proposée étant de complètement supprimer cette fonctionnalité pour PHP 7, ce qui permettrait de corriger quelques inconsistences. Cette RFC a ensuite été soumise aux votes, puis acceptée, avec 29 votes pour et 0 vote contre.

Andrea Faulds a corrigé un bug à cause duquel un caractère octal invalide entraînait la fin du parsing du nombre où il était placé — par exemple, $x = 0109 était équivalent à 010, soit 8 — et pas un échec pur et simple. Ce type de cas entraînera, à partir de PHP 7, une remontée d’erreur.

François Laupretre a proposé une solution visant à permettre aux caches d’opcodes de déterminer si une URI donnée est cachable ou non : RFC: Add is_cacheable() stream-wrapper operation. Les quelques retours ont eu l’air plutôt positifs.

Les votes sur la RFC: Objects as hash keys se sont terminés. Avec 26 votes “contre” et 6 votes “pour”, elle a été rejetée.

Sara Golemon a publié les résultats du vote sur la RFC: IntlChar class : avec 14 votes “pour” et 0 vote “contre”, elle est passée et ext/intl s’enrichit en conséquence d’une classe supplémentaire !

Les votes ont été ouvert sur la RFC: Turn gc_collect_cycles into function pointer, qui visait à permettre à des extensions de se brancher sur le Garbage Collector de PHP, en particulier en vue de profiling. Avec 18 votes pour et 0 vote contre, elle a été acceptée.

Les votes ont également été ouvert sur la RFC: Fast Parameter Parsing API, qui proposait de mettre en place un nouveau mode de déclaration de paramètres, plus rapide, pour les fonctions internes à PHP et à ses extensions. Cette proposition a été acceptée, avec 19 votes pour et 1 vote contre.

Yasuo Ohgaki a souligné que le comportement de foreach n’était pas toujours très intuitif et que PHP 7 serait une bonne occasion pour corriger cela. Tout à la fin du mois, Dmitry Stogov a rédigé la RFC: Fix foreach behavior, qui a été enrichie peu après, en vue d’uniformiser et de clarifier plusieurs cas un peu tordus (cette proposition apporterait aussi un gain potentiel de performances d’environ 1% sur certaines applications).

Stas Malyshev a annoncé l’ouverture des votes sur la RFC: Default constructors, qui proposait de systématiquement permettre d’appeler le constructeur d’une classe, y compris si elle n’en n’avait pas. Finalement, avec 27 votes pour et 20 votes contre, elle a été rejetée (une majorité de 2/3 était nécessaire pour qu’elle passe). Comme l’a fait remarquer Stas Malyshev, il est dommage que trop de personnes votant non n’expliquent souvent pas pourquoi. François Laupretre en a profité pour suggérer quelques idées qui pourraient peut-être améliorer les choses à ce niveau.

Suite à la discussion autour d’une PR répondant à une feature-request qui remontait à 2006, F & N Laupretre a rédigé la RFC: Add cyclic string replacements, qui propose d’ajouter un mode de remplacement cyclique aux fonctions str_[i]replace(). Une partie des retours ont été plutôt positifs, alors que d’autres ont indiqué que cette fonctionnalité ne leur semblait pas suffisamment importante pour avoir sa place dans la bibliothèque standard de PHP.

Andrea Faulds a noté que puisque PHP 7 semblait être l’occasion d’effectuer une petite passe de ménage, il pourrait être intéressant de faire quelque chose à propos des fonctions de génération de nombres aléatoires rand() et mt_rand() — la première étant lente et peu efficace, alors que c’est celle qu’un nouvel arrivant aura naturellement tendance à utiliser — et a suggéré un plan d’attaque. Les premiers retours ont été plutôt positifs, même si d’autres ont souligné qu’il était important de ne pas casser l’existant en supprimant des fonctions répandues.

F & N Laupretre a rédigé la RFC: Improve array to string conversion, qui propose soit de supprimer complètement la conversion tableau → chaine (qui donne aujourd’hui "Array" et génére une notice), soit de la gérer réellement. Il n’y a eu que peu de retour sur ce sujet, mais j’aimerais le voir progresser d’ici PHP 7, considérant que cette conversion n’est que rarement utile — et à chaque fois que j’ai rencontré cette notice, elle m’a permis d’identifier un bug !

Niklas Keller a suggéré qu’il pourrait être sympathique d’avoir un opérateur in, qui remplacerait à la fois in_array() et certains usages de strpos().

Bob Weinand a écrit la RFC: Remove the date.timezone warning qui propose de supprimer l’avertissement qui est actuellement généré lorsque l’on essaye d’utiliser une fonction de manipulation de date sans avoir configuré la timezone à utiliser (directive date.timezone). Supprimer cet avertissement serait appréciable, mais il est important de configurer correctement ce point, même si UTC semble souvent (mais pas toujours) être un choix raisonnable, et déterminer automatiquement la timezone du système n’est pas évident.

Michael Wallner a relancé la discussion autour de la RFC: Add pecl_http to core, qui propose d’inclure l’extension PECL pecl_http au cœur de PHP.

Suite à, entre autres, une remarque de Remi Collet en octobre à propos de problèmes de licence (qui sont suffisant pour justifier cette proposition) autour de l’extension ext/json de PHP, Jakub Zelenka a rédigé la RFC: Replacing current json extension with jsond, pour laquelle les votes ont été ouvert à la fin du mois.

Thomas Bley a annoncé la RFC: Allow error_handler callback parameters to be passed by reference, qui propose de permettre aux fonctions de gestion d’erreurs configurées via set_error_handler() de modifier leurs paramètres, qui seraient passés par référence, typiquement pour enrichir des messages d’erreurs. Xinchen Hui a souligné qu’utiliser un gestionnaire d’erreurs personnalisé était probablement plus adapté, dans ce type de cas — et Stas Malyshev a ajouté que modifier une donnée qui devrait être interne à PHP était étrange.



internals@lists.php.net est la mailing-list des développeurs de PHP ; elle est utilisée pour discuter des prochaines évolutions du langage, ainsi que pour échanger autour de suggestions d’améliorations ou de rapports de bugs.
Elle est publique, et tout le monde peut s’y inscrire depuis la page Mailing Lists, ou consulter ses archives en HTTP depuis php.internals ou depuis le serveur de news news://news.php.net/php.internals.



  1. Et février promet un joli pic, puisqu’il en est déjà à presque 2050 mails — et qu’il reste encore quelques jours avant la fin du mois ! 

  2. Il n’avait alors pas encore été décidé que PHP 5.7 ne sortirait pas. 

  3. Ferenc Kovacs a d’ailleurs noté que cela avait été proposé dès 2009 — et que cette idée revient sur le tapis à chaque fois que l’on parle de typage pour des scalaires ! 

In favor of RFC "Scalar Type Hints"

February 9, 2015 php, internals@, rfc, type-hint, english

Cet article est aussi disponible en français.


The Scalar Type Hints RFC for PHP 7 has first been initialized in December 2014. It went on with version 0.2 at the middle of January 2015, after changing several major ideas, and is now in version 0.3, integrating return types, as RFC Return Type Declarations has been accepted a few days ago.

Warning: this post is about a feature that is currently (beginning of February 2015) being discussed for PHP 7. As for any proposal being discussed, this feature might get accepted, or an alternative version could be, or it could even be rejected — be it for PHP 7.0 or for a later version. The truth about this feature — or its absence — will be in the PHP manual and in migration guides.

I’ve been following this RFC (and the previous ones) with some interest, and, as I’ve taken some time to play with it a bit last week, building PHP from the sources of the corresponding Git branch, I’ll try summarizing here why I think it is interesting. Please note this is my personnal opinion.

Why (scalar) type-hints?

PHP has been supporting type-hints1 on complex types for quite some time already: PHP 5.0 for objects, 5.1 for array and 5.4 for callable. The question of extending this support to scalar types (integer, float, boolean and string) as been discussed several times those last years, each time with a bit more support.

For me, type-hints, scalar or not, can and/or must fulfill several objectives:

  1. Make code more explicit: when reading the prototype of a function2, which is generally displayed by my IDE when I’m writing a function call, without having to go read either its source-code or documentation, types-hints allow developers to know which type of data that function expects.
  2. Ensure that, in the function itself, the data we have at our disposal is of the expected type — without having to write the corresponding checks ourselves.
  3. Be compatible with PHP’s flexible philosophy and history.
  4. Not break compatibility of libraries that specify type-hints with the code calling them, code which might not necessarily work with strict typing.

With the proposition this RFC introduces, if it passes, a function expecting an integer could be declared this way:

function my_function_01(int $myint)
{
    var_dump($myint);
}

If this function is called passing it something else than an integer as a parameter, the call will fail and a catchable error will be raised — like for the other kinds of already existing type-hints:

Catchable fatal error: Argument 1 passed to my_function_01() must be of the type integer, string given

Seeing this, this type-hinting idea for scalars doesn’t seem too hard to work with.

Some weak typing…

One of PHP’s great forces, one of the key elements of its accessibility, is its weak typing principle, where type-conversions are done when necessary.

Typically, with an URL like http://example.org/index.php?id=123, the $_GET['id'] element will contain the string "123" — which can be manipulated with pretty much all PHP functions as if it was an integer, without us having to worry about its real type: what matters is the data and the value it contains and the meaning we give them! This example also applies well to most of the database querying APIs, where results are often returned as strings.

This RFC has, in my eyes, the great advantage of going by default with weakly typed type-hints. This means, for the function presented a bit earlier, both following calls would be valid:

my_function_01(42);
my_function_01('42');

In both cases, the $myint variable received by the function will be an integer: using the specified type-hint, PHP will do an automatic conversion of the given value, following the same rules in place everywhere else in the language!

This means the output will look like this:

int(42)
int(42)

Still, passing a value that cannot be converted to an integer will cause the error shown earlier to be raised. For instance, with:

my_function_01('plop');

We’ll get, I repeat, the following output:

Catchable fatal error: Argument 1 passed to my_function_01() must be of the type integer, string given

So, in a few words, this RFC introduces a flexible mecanism for type-hinting, that answers both needs:

  • of the developers of the function, who want to receive some data of the type they specified,
  • and of the developers who use this function, who want to keep using PHP’s weak typing approach.

This default flexible behavior also has the advantage of integrating well with PHP’s traditional approach and not breaking compatibility of existing code.

And some strict typing!

Still, even if PHP has an history and tradition of being flexible, many developers tend, since a few years, to work with a more strict approach to typing, using variables of the integer type when it comes to storing integer values, variables of the float type when it’s about storing decimal values, and so on.

At a certain level, this tendency is shown by the almost systematic use of strict comparison operators like === or !==. At another level, it is also found in the appreciation for the type annotations feature of the Hack language.

Well, as it is, this RFC also answers this need for strict typing!

To allow switching to strict scalar type-hinting mode, a new declare()3 directive is added: strict_types.

Inside a declare(strict_types=1) block, all function calls with scalar type-hints will be done in strict type mode. For example:

declare(strict_types=1) {
    my_function_01('42');
}

The my_function_01() function is defined as expecting an integer as a parameter. As we have given it a string after activating the strict typing mode, this call will cause an error to be raised:

Catchable fatal error: Argument 1 passed to my_function_01() must be of the type integer, string given, 
  called in .../test-01.php on line 9 
  and defined in .../test-01.php on line 17

Instead of wrapping portions of code in declare(strict_types=1) blocks, using this directive at the beginning of a file is also possible — in which case all function calls made from this file will be in strict typing mode:

<?php
declare(strict_types=1);
// All functions/methods calls made from this 
// file will be using strict typing

// Valid => int(42) 
my_function_01(42);

// Invalid
my_function_01('42');
?>

With this directive, this RFC answers both the needs and wishes of those who prefer working with strict types, even if going against the flexible traditional usages of PHP, and of those who prefer working with weak types. In each function, as shown earlier, the types of data received as parameters are those defined and expected by the function’s authors.

A more consequent example?

To visualize things a bit better, let’s consider the following class, which would be part of a library:

// We could or not use a declare(strict_types=1) here, for
// function calls made from this file.

class MyLib
{
    public function expectInt(int $myint) {
        printf("%s( %s )\n\n", __METHOD__, str_replace("\n", " ", var_export($myint, true)));
    }

    public function expectFloat(float $myfloat) {
        printf("%s( %s )\n\n", __METHOD__, str_replace("\n", " ", var_export($myfloat, true)));
    }

    public function expectString(string $mystring) {
        printf("%s( %s )\n\n", __METHOD__, str_replace("\n", " ", var_export($mystring, true)));
    }
}

We’ll also setup an error handler, tasked with intercepting (amongst others) catchable errors that will be raised if type-hints are not respected:

set_error_handler(function (int $errno , string $errstr, string $errfile, int $errline, array $errcontext) {
    printf("Error:\n");
    printf("  * errno = %s\n", var_export($errno, true));
    printf("  * errstr = %s\n", var_export($errstr, true));
    printf("  * errfile = %s\n", var_export($errfile, true));
    printf("  * errline = %s\n", var_export($errline, true));
    printf("  * errcontext = %s\n", str_replace("\n", " ", var_export($errcontext, true)));

    return true;    // continue working
});

We’ll now use this class from a file in weak typing mode (so, not using the declare() directive):

// No declare() on top of this file => weak mode

$obj = new MyLib();

// Working calls
printf("Working calls:\n\n");
$obj->expectInt(123456);
$obj->expectFloat(3.1415);
$obj->expectString('Hello, World!');
$obj->expectString('123456789');

// Those calls will also work, as we are not in strict_types mode
// => The usual conversions will apply ("weak" typing)
printf("Other working calls:\n\n");
$obj->expectInt('123456');          // MyLib::expectInt( 123456 )
$obj->expectFloat('3.1415');        // MyLib::expectFloat( 3.1415000000000002 )
$obj->expectString(123456789);      // MyLib::expectString( '123456789' )

// Appels qui ne fonctionnent pas, puisque les transtypages habituels ne sont pas possibles
printf("Calls that don't work:\n\n");
$obj->expectInt('abcdef');
$obj->expectFloat([123, 'hello']);
$obj->expectString($obj);

Executing this example will generate the following output (reformatted a bit, to facilitate reading):

Working calls:

    MyLib::expectInt( 123456 )
    MyLib::expectFloat( 3.1415000000000002 )
    MyLib::expectString( 'Hello, World!' )
    MyLib::expectString( '123456789' )

Other working calls:

    MyLib::expectInt( 123456 )
    MyLib::expectFloat( 3.1415000000000002 )
    MyLib::expectString( '123456789' )

Calls that don't work:

    Error:
      * errno = 4096
      * errstr = 'Argument 1 passed to MyLib::expectInt() must be of the type integer, string given, called in .../test-02-nostrict.php on line 34 and defined'
      * errfile = '.../lib.php'
      * errline = 6
      * errcontext = array ( )
    MyLib::expectInt( 'abcdef' )

    Error:
      * errno = 4096
      * errstr = 'Argument 1 passed to MyLib::expectFloat() must be of the type float, array given, called in .../test-02-nostrict.php on line 35 and defined'
      * errfile = '.../lib.php'
      * errline = 10
      * errcontext = array ( )
    MyLib::expectFloat( array (   0 => 123,   1 => 'hello', ) )

    Error:
      * errno = 4096
      * errstr = 'Argument 1 passed to MyLib::expectString() must be of the type string, object given, called in .../test-02-nostrict.php on line 36 and defined'
      * errfile = '.../lib.php'
      * errline = 14
      * errcontext = array ( )
    MyLib::expectString( MyLib::__set_state(array( )) )

This clearly shows that in weak typing mode, when automatic type conversions were possible, PHP used them. On the other hand, when there were no possible type conversions, errors have been raised, preventing (if my error handler hadn’t naively returned true) the executions of functions called with invalid parameters.

Now, let’s see some function calls from a file in strict typing mode:

declare(strict_types=1);  // strict mode !

$obj = new MyLib();

// Working calls
printf("Working calls:\n\n");
$obj->expectInt(123456);
$obj->expectFloat(3.1415);
$obj->expectString('Hello, World!');
$obj->expectString('123456789');

// Calls that won't work, as we are here in strict_types mode
printf("Calls that don't work:\n\n");
$obj->expectInt('abcdef');
$obj->expectFloat([123, 'hello']);
$obj->expectString(123456789);

The output we’ll get, this time, will look like this (once again, modified a bit to facilitate reading):

Working calls:

    MyLib::expectInt( 123456 )
    MyLib::expectFloat( 3.1415000000000002 )
    MyLib::expectString( 'Hello, World!' )
    MyLib::expectString( '123456789' )

Calls that don't work:

    Error:
      * errno = 4096
      * errstr = 'Argument 1 passed to MyLib::expectInt() must be of the type integer, string given, called in .../test-02-nostrict.php on line 34 and defined'
      * errfile = '.../lib.php'
      * errline = 6
      * errcontext = array ( )
    MyLib::expectInt( 'abcdef' )

    Error:
      * errno = 4096
      * errstr = 'Argument 1 passed to MyLib::expectFloat() must be of the type float, array given, called in .../test-02-nostrict.php on line 35 and defined'
      * errfile = '.../lib.php'
      * errline = 10
      * errcontext = array ( )
    MyLib::expectFloat( array (   0 => 123,   1 => 'hello', ) )

    Error:
      * errno = 4096
      * errstr = 'Argument 1 passed to MyLib::expectString() must be of the type string, integer given, called in .../test-02-nostrict.php on line 36 and defined'
      * errfile = '.../lib.php'
      * errline = 14
      * errcontext = array ( )
    MyLib::expectString( 123456789 )

This time, the only calls that have worked are those where data types, and not only their values, did match the type-hints specified when declaring the methods: no type conversion has automatically been done!

Strict typing… by calling file? Or by function called?

An idea as been discussed several times: it could be up to each function to decide if, when it’s called, types must be checked in weak (if automatic conversions can be applied) or in strict (if an error must be raised when a type is incorrect, even if the value is acceptable) mode.

With such a proposition, it’s the authors of a library who would decide if it can be used by an application developed with a weak types logic or if it may only be used by applications written with a strict approach to typing.

In other words, if tomorrow the authors of one of the numerous libraries I use in my projects were to start using type-hints, they could decide that my application, in which I sometimes have integer values in variables of string type, is not worth using their library — and that errors should be raised here and there!

I don’t understand how this could be a good idea — or even a viable idea in anyway, for that matters!

Type-hints in a function’s declaration are there to:

  • indicate the callers what kind of values it expects,
  • and to guarantee data as seen by the function are of the specified types.

Having or not an automatic conversion doesn’t have to be visible at the level of the called function: only the callers can decide which behavior is adapted: it’s them who know if their application works with a weak or strict typing logic!

In this mater, the declare() directive, that has to be set on top of each file (or around each block) where calls can/must be made in strict mode, really answers our needs well: it offers possibilities, without at the same time imposing more constraints than we can accept.

And for return types?

As RFC Return Type Declarations has been accepted while this one was still under discussion, a v0.3 has been published, adding scalar type-hints to return types.

The general idea is the same than for parameters types: in weak mode, conversions will automatically be applied if they are needed and possible, while in strict mode, an error will be raised if a function tries to return a value that’s not of the right type.

The major difference resides in the fact the weak or strict mode is not decided when the function is called, but when it’s declared. This is because the persons that are best able to determine whether their function or library returns the right types or needs conversions really are its authors!

For example, let’s consider the two following functions’ declarations, both written while we are in weak mode:

// No specific declare() => weak typing mode

// Function that returns an integer, like planned
// => Everything is OK!
function my_function_01(int $a, int $b) : int
{
    return $a + $b;
}

// Function that tries to return a string instead of an integer
// It's declared while we are in weak mode => conversion
function my_function_02(int $a, int $b) : int
{
    return strval($a + $b);
}

We can call these two functions, while we are either in weak or in strict mode:

var_dump( my_function_01(2, 5) );
var_dump( my_function_02(2, 5) );

And the output will be the same in both cases:

int(7)
int(7)

The second function tried to return a string instead of an integer, but as it’s been declared in weak mode and the string could be converted to an integer, this conversion has taken place.

On the other hand, if we had defined those two same functions while being in strict mode, our two calls would have produced the following output (no matter if they had been made from a weak or a strict portion of code):

int(7)

Catchable fatal error:  Return value of my_function_02() must be of the type integer, string returned 
  in .../return-02.php on line 15

As you’ll have understood, the second call failed, as the function was declared to return an integer, in strict mode, and tried to return a string.

declare(), use strict, … directives

During discussions I’ve read and/or participated to, I’ve several times seen that declare(strict_types=1) would be ugly, that it would not be easy to memorize or type, or that a use strict might be better.

With a tiny bit of bad faith, if I could answer with only one thing, it would be:

The \ namespaces separator introduced in PHP 5.3, while PHP 5.3 was already in alpha versions phase and :: had been evoked for a very long time, everyone said it was ugly and un-easy to type…

Still, a few years later, we all got used to it and we can’t say namespaces have not been a real success ;-)

With some additional arguments:

  • use strict might cause some confusion, as use is already used for namespaces, today — it’s even possible to declare a namespace called strict, even if trying to import it without aliasing it causes a Fatal error: You seem to be trying to use a different language... ;-)
  • Using an option called strict and not strict_types would be lying: there are many things we could want to make more strict in PHP, and here, the proposition is about activating a strict mode for only one of them.
  • After typing this directive a few times, it will naturally fall under our fingers4 — and once PHP 7 is released, I’m sure our IDEs will know how to auto-complete it ;-)

In other words, even if this directive feels a bit strange at first sight, I have no doubt we’ll easily get used to it, especially considering the advantages it bring!

What now?

First of all, this RFC has entered voting phase a few days ago. Votes will end on February 19.

If this RFC is accepted, it will be possible to think about going a bit farther, especially re-thinking about the idea of nullables types — idea that might eventually arrive with a later minor version, such as PHP 7.1 ou 7.2.

For now, votes are at 41 yes and 27 no. Considering 2/3 positives votes are required for the RFC to pass, things are not yet decided and could go either one way or the other!

At the same time, even if the RFC is in its voting phase, additional ideas are still being discussed, like, no later than yesterday evening:

  • Possibly adding a numeric type-hint for numbers, accepting both integers and floats. I don’t really have any opinion on this (for now).
  • What could be a switch to a marker on PHP’s opening tag, like <?php strict. Why not, but maybe more with something like <?php strict_types, to avoid closing the door in front of other ideas that might want to make PHP more strict?

My opinion, in a few words

I have followed discussions about the idea of type-hinting for scalars for a while and I have to admit that, this time, I think this proposition is pretty good, mostly thanks to the following points:

  • This feature is not enabled by default; so, it doesn’t break existing code.
  • Type-hints ensure that data received by functions that specify them in their declarations will be of the type they expect, no matter if they are called in weak or strict mode.
  • Using a flexible typing mechanism by default fits well with PHP’s spirit, won’t be destabilizing for beginners, and will allow us to gradually adapt libraries and/then applications.
  • It’s the callers who indicate when they’re ready to switch to strict typing for calls they do, once their code works with strict types.
  • And it’s the authors of each library who determine — and they are the best placed to take this decision — if they think their code will or not work with strict return types.

I would add that Andrea, author of this RFC, did a really great job, be it on the RFC itself, which includes much details, on discussions about her proposition, and in dealing with the large amount of feedback it has generated!

Well, in conclusion, I really hope this RFC will pass!


  1. As a matter of facts, PHP’s existing type-hints are not really hints, but more like strong checks, as errors are raised if they are not respected. 

  2. In this post, I’ll talk about functions or methods, depending on the examples I’ll present. The principle is exactly the same in both cases, as a method is pretty much nothing more than a function placed inside an object. 

  3. The declare() instruction itself is not new: it has existed for quite some time and aims to alter the behavior of PHP’s engine. It is not well-known though, as the currently existing directives are not really useful nor used. 

  4. I can already type declare(strict_types=1) without having to think much… And I’ve only spent a few half-hours playing with it! 

En faveur de la RFC "Scalar Type Hints"

9 février 2015 php, internals@, rfc, type-hint

This post is also available in English.


La RFC Scalar Type Hints pour PHP 7 a été initialisée en décembre 2014. Elle est passée en version 0.2 mi-janvier 2015, après une refonte de plusieurs idées fondatrices et est maintenant en version 0.3 qui intègre les types de retours, puisque la RFC Return Type Declarations a été acceptée il y a quelques jours.

Avertissement : cet article fait référence à une fonctionnalité en cours de discussion (début février 2015) pour PHP 7. Comme pour toute proposition en cours de discussion, il est possible que cette fonctionnalité soit acceptée, qu’une version alternative le soit, ou même qu’elle soit entièrement refusée — que ce soit pour PHP 7.0 ou pour une version ultérieure. La vérité à propos de cette fonctionnalité — ou de son absence — se trouvera dans le manuel de PHP et dans les guides de migration.

Je suis cette RFC (et celles qui l’ont précédées) avec un certain intérêt et puisque j’ai pris le temps de jouer un peu avec la semaine dernière, en construisant PHP depuis les sources de la branche Git correspondant, je vais essayer de résumer ici pourquoi je pense qu’elle est intéressante. Notez qu’il s’agit de mon avis personnel.

Pourquoi des type-hints (scalaires) ?

PHP supporte les type-hints1 sur les types complexes depuis déjà un bon moment : PHP 5.0 pour les objets, 5.1 pour array et 5.4 pour callable. La question d’étendre ce support aux types scalaires (entier, flottant, booléen et chaîne de caractères) est revenue plusieurs fois ces dernière années, à chaque fois avec un peu plus de soutien.

À mes yeux, les type-hints, scalaires ou non, peuvent et/ou doivent répondre à plusieurs objectifs :

  1. Rendre le code explicite : dès la lecture du prototype d’une fonction2, qui est souvent affiché par mon IDE lorsque j’écris un appel de fonction, sans avoir à aller lire ni son code-source ni sa documentation, les type-hints permettent de savoir quels types de données elle attend.
  2. Assurer que, au sein de la fonction, on ait une donnée du type attendu — sans avoir à coder soi-même les vérifications correspondantes.
  3. Être compatibles avec la philosophie et l’historique souple de PHP.
  4. Ne pas casser la compatibilité des librairies spécifiant des type-hints avec le code les appelant, code qui ne travaille pas nécessairement avec du typage strict.

Avec la proposition introduite par cette RFC, si elle passe, une fonction attendant un entier pourrait être déclarée comme ceci :

function ma_fonction_01(int $entier)
{
    var_dump($entier);
}

Si cette fonction est appelée en lui passant en paramètre autre chose qu’un entier, l’appel échouera et une erreur rattrapable sera levée — comme pour les autres type-hints actuellement disponibles :

Catchable fatal error: Argument 1 passed to ma_fonction_01() must be of the type integer, string given

Vu comme ça, ce type-hinting pour les scalaires ne semble guère difficile à manipuler.

Du typage souple…

Une des grandes forces de PHP, un des éléments clef à la base de son accessibilité, est son principe de typage souple, avec des conversions de types effectuées lorsque nécessaire.

Par exemple, pour une URL comme http://example.org/index.php?id=123, l’entrée $_GET['id'] contiendra la chaîne de caractères "123" — qui pourra être manipulée avec la quasi-totalité des fonctions de PHP comme s’il s’agissait d’un entier, sans que nous n’ayons à nous soucier de son type réel : c’est la donnée et la valeur contenues et le sens qu’on lui donne qui sont importants ! Cet exemple s’applique d’ailleurs aussi assez bien à la majeure partie des API de requêtage de bases de données, où les résultats sont souvent renvoyés sous forme de chaînes de caractères.

Cette RFC a ce qui est pour moi l’immense avantage de partir par défaut sur des type-hints avec du typage souple. Ainsi, avec la fonction définie un peu plus haut, les appels suivants seraient tous deux valides :

ma_fonction_01(42);
ma_fonction_01('42');

Dans les deux cas, la variable $entier reçue par la fonction sera un entier : à partir du type-hint spécifié, PHP effectuera une conversion automatique de la valeur passée, en suivant les règles déjà en place partout ailleurs dans le langage !

La sortie obtenue sera donc la suivante :

int(42)
int(42)

En revanche, passer une valeur qui ne puisse être convertie en entier mènera à l’erreur reproduite plus haut. Par exemple, avec :

ma_fonction_01('plop');

La sortie obtenue sera, je me répète :

Catchable fatal error: Argument 1 passed to ma_fonction_01() must be of the type integer, string given

Cette RFC propose donc un mécanisme de type-hinting souple, qui répond à la fois aux besoins :

  • du développeur de la fonction, qui souhaite recevoir une donnée du type qu’il a spécifié,
  • et du développeur utilisant cette fonction, qui souhaite continuer à bénéficier du typage souple de PHP.

Ce fonctionnement en mode souple par défaut a également l’avantage de bien s’intégrer à l’approche traditionnelle de PHP et de ne pas casser la compatibilité du code existant.

Et du typage strict !

Toutefois, malgré l’historique et la tradition souple de PHP, nombre développeurs ont tendance depuis quelques années à travailler avec un typage plus strict, en utilisant des variables de type entier lorsqu’il s’agit de contenir des valeurs entières, des variables de type flottant lorsqu’il s’agit de stocker des valeurs décimales et ainsi de suite.

À une certaine échelle, cette tendance se manifeste par l’emploi devenu quasi-systématique des opérateurs de comparaison stricts comme === ou !==. À un autre niveau, elle se retrouve également dans l’engouement pour la fonctionnalité d’annotations de types du langage Hack.

Et bien, cette RFC répond également à ce besoin de typage strict !

Pour basculer en mode de type-hinting scalaire strict, une nouvelle directive declare()3 est ajoutée : strict_types.

Au sein d’un bloc declare(strict_types=1), tous les appels de fonctions avec des type-hints scalaires seront effectués en mode de typage strict. Par exemple :

declare(strict_types=1) {
    ma_fonction_01('42');
}

La fonction ma_fonction_01() est définie comme attendant un entier en paramètre. Puisque nous avons passé une chaîne de caractères après avoir activé le mode de typage strict, l’appel reproduit ci-dessus entraînera la levée d’une erreur :

Catchable fatal error: Argument 1 passed to ma_fonction_01() must be of the type integer, string given, 
  called in .../test-01.php on line 9 
  and defined in .../test-01.php on line 17

Au lieu d’encapsuler des portions de code dans des blocs declare(strict_types=1), il est également possible d’employer cette directive au début d’un fichier — auquel cas tous les appels de fonctions effectués au sein de ce fichier seront en mode de typage strict :

<?php
declare(strict_types=1);
// Tous les appels de fonctions/méthodes effectués depuis
// ce fichier seront en typage strict

// Valide => int(42) 
ma_fonction_01(42);

// Invalide
ma_fonction_01('42');
?>

Avec cette directive, cette RFC répond aux besoins et souhaits de ceux qui préfèrent travailler avec des types stricts, quitte à rompre avec les usages traditionnels de souplesse de PHP. Au sein de chaque fonction, comme précédemment, les types des données reçues en paramètres sont ceux définis et attendus par l’auteur de la fonction.

Un exemple un peu plus conséquent ?

Pour visualiser un peu mieux les choses, considérons la classe suivante, faisant partie d’une bibliothèque :

// On pourrait ou non mettre un declare(strict_types=1) ici, pour jouer
// sur les appels de fonctions effectués depuis ce fichier.

class MaLib
{
    public function expectInt(int $entier) {
        printf("%s( %s )\n\n", __METHOD__, str_replace("\n", " ", var_export($entier, true)));
    }

    public function expectFloat(float $flottant) {
        printf("%s( %s )\n\n", __METHOD__, str_replace("\n", " ", var_export($flottant, true)));
    }

    public function expectString(string $chaine) {
        printf("%s( %s )\n\n", __METHOD__, str_replace("\n", " ", var_export($chaine, true)));
    }
}

Mettons également en place un gestionnaire d’erreurs, chargé d’intercepter (entre autres) les erreurs rattrapables qui seront levées si les type-hints ne sont pas respectés :

set_error_handler(function (int $errno , string $errstr, string $errfile, int $errline, array $errcontext) {
    printf("Erreur :\n");
    printf("  * errno = %s\n", var_export($errno, true));
    printf("  * errstr = %s\n", var_export($errstr, true));
    printf("  * errfile = %s\n", var_export($errfile, true));
    printf("  * errline = %s\n", var_export($errline, true));
    printf("  * errcontext = %s\n", str_replace("\n", " ", var_export($errcontext, true)));

    return true;    // on continue le traitement
});

Utilisons maintenant cette classe depuis un fichier en mode de typage souple (donc, sans utiliser la directive declare() vue plus haut) :

// Pas de declare() en haut du fichier => mode souple

$obj = new MaLib();

// Appels qui fonctionnent
printf("Appels qui fonctionnent :\n\n");
$obj->expectInt(123456);
$obj->expectFloat(3.1415);
$obj->expectString('Hello, World!');
$obj->expectString('123456789');

// Appels qui fonctionnent aussi, puisque nous ne sommes pas en mode strict_types
// => Les transtypages habituels sont effectués (typage "souple")
printf("Appels qui fonctionnent aussi :\n\n");
$obj->expectInt('123456');          // MaLib::expectInt( 123456 )
$obj->expectFloat('3.1415');        // MaLib::expectFloat( 3.1415000000000002 )
$obj->expectString(123456789);      // MaLib::expectString( '123456789' )

// Appels qui ne fonctionnent pas, puisque les transtypages habituels ne sont pas possibles
printf("Appels qui ne fonctionnent pas :\n\n");
$obj->expectInt('abcdef');
$obj->expectFloat([123, 'hello']);
$obj->expectString($obj);

La sortie obtenue (un peu reformatée pour faciliter la lecture) en exécutant cet exemple sera la suivante :

Appels qui fonctionnent :

    MaLib::expectInt( 123456 )
    MaLib::expectFloat( 3.1415000000000002 )
    MaLib::expectString( 'Hello, World!' )
    MaLib::expectString( '123456789' )

Appels qui fonctionnent aussi :
    MaLib::expectInt( 123456 )
    MaLib::expectFloat( 3.1415000000000002 )
    MaLib::expectString( '123456789' )

Appels qui ne fonctionnent pas :

    Erreur :
      * errno = 4096
      * errstr = 'Argument 1 passed to MaLib::expectInt() must be of the type integer, string given, called in .../test-02-nostrict.php on line 34 and defined'
      * errfile = '.../lib.php'
      * errline = 6
      * errcontext = array ( )
    MaLib::expectInt( 'abcdef' )

    Erreur :
      * errno = 4096
      * errstr = 'Argument 1 passed to MaLib::expectFloat() must be of the type float, array given, called in .../test-02-nostrict.php on line 35 and defined'
      * errfile = '.../lib.php'
      * errline = 10
      * errcontext = array ( )
    MaLib::expectFloat( array (   0 => 123,   1 => 'hello', ) )

    Erreur :
      * errno = 4096
      * errstr = 'Argument 1 passed to MaLib::expectString() must be of the type string, object given, called in .../test-02-nostrict.php on line 36 and defined'
      * errfile = '.../lib.php'
      * errline = 14
      * errcontext = array ( )
    MaLib::expectString( MaLib::__set_state(array( )) )

Ceci met clairement en évidence le fait qu’en mode de typage souple, dans les cas où des conversions de types automatiques étaient possibles, PHP les a jouées. Par contre, dans les cas inverses, des erreurs ont été levées, empêchant (si mon gestionnaire d’erreur n’avait pas bêtement retourné true) l’exécution des fonctions appelées avec des paramètres incorrects.

Passons maintenant à des appels depuis un fichier en mode de typage strict :

declare(strict_types=1);  // Mode strict !

$obj = new MaLib();

// Appels qui fonctionnent
printf("Appels qui fonctionnent :\n\n");
$obj->expectInt(123456);
$obj->expectFloat(3.1415);
$obj->expectString('Hello, World!');
$obj->expectString('123456789');

// Appels qui ne fonctionnent pas, puisque nous sommes ici en mode strict_types
printf("Appels qui ne fonctionnent pas :\n\n");
$obj->expectInt('abcdef');
$obj->expectFloat([123, 'hello']);
$obj->expectString(123456789);

La sortie obtenue (également retouchée pour faciliter la lecture), cette fois, sera la suivante :

Appels qui fonctionnent :

    MaLib::expectInt( 123456 )
    MaLib::expectFloat( 3.1415000000000002 )
    MaLib::expectString( 'Hello, World!' )
    MaLib::expectString( '123456789' )

Appels qui fonctionnent aussi :

    MaLib::expectInt( 123456 )
    MaLib::expectFloat( 3.1415000000000002 )
    MaLib::expectString( '123456789' )

Appels qui ne fonctionnent pas :

    Erreur :
      * errno = 4096
      * errstr = 'Argument 1 passed to MaLib::expectInt() must be of the type integer, string given, called in .../test-02-nostrict.php on line 34 and defined'
      * errfile = '.../lib.php'
      * errline = 6
      * errcontext = array ( )
    MaLib::expectInt( 'abcdef' )

    Erreur :
      * errno = 4096
      * errstr = 'Argument 1 passed to MaLib::expectFloat() must be of the type float, array given, called in .../test-02-nostrict.php on line 35 and defined'
      * errfile = '.../lib.php'
      * errline = 10
      * errcontext = array ( )
    MaLib::expectFloat( array (   0 => 123,   1 => 'hello', ) )

    Erreur :
      * errno = 4096
      * errstr = 'Argument 1 passed to MaLib::expectString() must be of the type string, integer given, called in .../test-02-nostrict.php on line 36 and defined'
      * errfile = '.../lib.php'
      * errline = 14
      * errcontext = array ( )
    MaLib::expectString( 123456789 )

Cette fois, les seuls appels qui ont fonctionné sont ceux où les types des données, et plus uniquement leurs valeurs, respectaient les type-hints positionnés lors de la déclaration des méthodes : aucune conversion de type n’a été automatiquement effectuée !

Typage strict… par fichier appelant ? Ou par fonction appelée ?

Une idée est revenue plusieurs fois pendant les débats : ce serait à chaque fonction de déterminer si, lors de ses appels, les types doivent être vérifiés en mode souple (si des conversions automatiques peuvent être appliquées lorsqu’elles sont possibles) ou en mode strict (si une erreur doit être levée dès qu’un type est incorrect, même si la valeur serait acceptable).

Avec un tel fonctionnement, c’est l’auteur d’une bibliothèque qui déciderait si celle-ci peut être utilisée dans une application développée avec une logique de types souples ou si elle ne doit être utilisable que par des applications écrites avec une approche du typage stricte.

Autrement dit, si demain l’auteur d’une des nombreuses bibliothèques que j’utilise dans mes projets décidait d’utiliser des type-hints, il pourrait décider que mon application, où j’ai parfois des valeurs entières dans des variables de type chaîne de caractères, n’est pas digne d’utiliser sa bibliothèque — et que des erreurs devraient être levées un peu partout !

Je ne comprends pas en quoi cette approche pourrait être une bonne idée — ni même une idée viable en quelque façon que ce soit !

Les type-hints dans une déclaration de fonction sont là pour :

  • indiquer à l’appelant quels types de valeurs elle attend,
  • et pour garantir que les données vues par la fonction sont des types définis.

Qu’il y ait ou non une conversion automatique n’a pas à être visible au niveau de la fonction appelée : seul l’appelant est à même de décider quel comportement doit être adopté : c’est lui qui sait si son application travaille sur une logique de typage souple ou strict !

En cela, la directive declare(), à positionner en haut de chaque fichier (ou autour de chaque bloc) où les appels peuvent/doivent être effectués en mode strict, répond à mes yeux parfaitement au besoin : elle offre des possibilités, sans pour autant imposer de fonctionnement plus contraignant que nous ne sommes en mesure d’accepter.

Et pour les types de retour ?

Puisque la RFC Return Type Declarations a été acceptée alors que celle-ci était en cours de discussion, une v0.3 a été publiée, ajoutant les type-hints scalaires aux types de retour.

Le principe global est le même que pour les types de paramètres : en mode souple, des conversions sont automatiquement effectuées si elles sont nécessaires et possibles, alors qu’en mode strict, une erreur est levée si une fonction essaye de retourner une valeur qui n’est pas du bon type.

La différence majeure réside dans le fait que le mode souple ou strict n’est pas décidé au moment de l’appel de la fonction, mais lors de sa déclaration. En effet, la personne la mieux placée pour déterminer si sa fonction ou sa bibliothèque retourne les bons types ou a besoin de conversions est bien l’auteur de celle-ci !

Par exemple, considérons les deux déclarations de fonctions suivantes, toutes deux écrites alors que nous sommes en mode souple :

// Pas de declare() spécifique => mode de typage souple

// Fonction qui retourne un entier, comme prévu
// => Tout va bien !
function ma_fonction_01(int $a, int $b) : int
{
    return $a + $b;
}

// Fonction qui essaye de retourner une chaine au lieu d'un entier
// Elle est déclarée alors qu'on est en mode souple => conversion
function ma_fonction_02(int $a, int $b) : int
{
    return strval($a + $b);
}

On peut appeler ces deux fonctions, que l’on soit en mode souple ou en mode strict :

var_dump( ma_fonction_01(2, 5) );
var_dump( ma_fonction_02(2, 5) );

Et la sortie obtenue sera la même dans les deux cas :

int(7)
int(7)

La seconde fonction a essayé de retourner une chaîne de caractères au lieu d’un entier comme spécifié, mais puisqu’elle a été déclarée en mode souple et que le chaîne pouvait être convertie en entier, cette conversion a eu lieu.

À l’inverse, si nous avions défini ces deux même fonctions alors que nous étions en mode strict, la sortie obtenue par nos deux appels serait la suivante, que ces appels soit réalisés depuis une portion de code en mode souple ou en mode strict :

int(7)

Catchable fatal error:  Return value of ma_fonction_02() must be of the type integer, string returned 
  in .../return-02.php on line 15

Vous l’aurez compris, le second appel a échoué, puisque la fonction devait retourner un entier, en mode strict, et qu’elle a essayé de retourner une chaîne de caractères.

Directives declare(), use strict, …

Au cours des échanges que j’ai lu et/ou auxquels j’ai participé, plusieurs fois est revenue la remarque que la directive declare(strict_types=1) serait moche, qu’elle ne serait pas facile à mémoriser ou à taper, voire même qu’un use strict serait préférable.

Avec un brin de mauvaise foi, si je n’avais qu’une chose à répondre, ce serait :

Le séparateur d’espaces de noms \ introduit avec PHP 5.3, alors même que PHP 5.3 était déjà en phase de versions alpha et que :: avait été évoqué pendant un très long moment, lui aussi, tout le monde a dit qu’il était moche et pas pratique à taper…

Et pourtant, quelques années après, on s’y est tous fait et on ne peut pas dire que les espaces de noms ne sont pas un réel succès ;-)

En argumentant un peu plus :

  • use strict risquerait de porter à confusion, puisque use est déjà utilisé pour les espaces de noms, aujourd’hui — il est d’ailleurs possible de déclarer un espace de noms nommé strict, même si essayer de l’importer sans l’aliaser entraîne une Fatal error: You seem to be trying to use a different language... ;-)
  • Utiliser une option nommée strict et non strict_types serait mentir : il y a plein de choses que l’on pourrait vouloir rendre plus strictes en PHP et il s’agit ici d’activer un mode strict uniquement pour une d’entre elles.
  • Après avoir tapé quelques fois cette directive, elle nous tombera naturellement sous les doigts4 — et une fois PHP 7 sortie, je suis certain que nos IDE sauront l’auto-compléter ;-)

Autrement dit, même si cette directive semble un peu étrange au premier abord, je n’ai aucun doute sur le fait que nous nous y habituerons sans mal, surtout considérant les avantages qu’elle apporte !

Et pour la suite ?

Pour commencer, cette RFC est entrée en phase de votes il y a quelques jours. Ceux-ci se termineront le 19 février.

Si cette RFC passe, il deviendra temps de réfléchir à aller un peu plus loin, notamment en repensant à la notion de types nullables — idée qui pourrait éventuellement arriver pour une version mineure ultérieure, comme PHP 7.1 ou 7.2.

Pour l’instant, les votes en sont à 41 pour et 27 contre. Considérant qu’il faudrait 2/3 de votes positifs pour qu’elle soit validée, les choses ne sont pas encore décidées et la balance pourrait aussi bien pencher d’un côté que de l’autre !

En parallèle, alors même que la RFC est en phase de votes, des idées continuent à être lancées, comme, pas plus tard qu’hier soir :

  • La possibilité d’un type-hint numeric pour les nombres, qu’ils soient entiers ou flottants. Je n’ai pas vraiment d’opinion sur ce point (pour l’instant).
  • Une éventuelle bascule vers un marqueur au niveau de la balise PHP ouvrante, comme <?php strict. Pourquoi pas, mais peut-être plus avec quelque chose du style <?php strict_types pour ne pas fermer de porte à d’autres points visant à rendre PHP plus strict ?

Mon avis en quelques mots

Cela fait un moment que je suis avec intérêt les différents débats qui ont eu lieu autour de l’idée de type-hinting pour les scalaires et je dois avouer que, cette fois, je suis conquis, principalement grâce aux points suivants :

  • La fonctionnalité n’est pas activée par défaut ; donc pas de cassure de l’existant.
  • Les type-hints garantissent que les données reçues par des fonctions en spécifiant lors de leur déclaration seront bien des types attendus, qu’elles soient appelées en mode souple ou strict.
  • L’utilisation d’un typage souple par défaut correspond bien à l’esprit de PHP, ne sera pas déstabilisant pour les débutants et permettra d’adapter graduellement les bibliothèques et/puis les applications.
  • C’est l’appelant qui détermine lorsqu’il est prêt à passer à un typage strict lors des appels qu’il effectue, une fois que son code travaille avec des types stricts.
  • Et c’est l’auteur de chaque librairie qui détermine — et c’est lui le mieux placé pour cela — si il estime que son code fonctionnera ou non avec des types de retour stricts.

J’ajouterais qu’Andrea, auteur de cette RFC, a fait un super boulot, tant sur la RFC qui est bien détaillée que sur les échanges autour de sa proposition, ainsi qu’au niveau de la prise en compte des très nombreux retours qui lui ont été adressés !

Bref, j’espère de tout cœur que cette RFC passera !


  1. En réalité, les type-hints existant de PHP ne sont pas des hints, mais des vérifications fortes, puisque des erreurs sont levées s’ils ne sont pas respectés. 

  2. Dans cet article, je parlerai de fonctions ou de méthodes, selon les exemples présentés. Le principe est systématiquement le même dans les deux cas, une méthode n’étant à peu de choses près qu’une fonction placée au sein d’un objet. 

  3. L’instruction declare() en elle-même n’est pas nouvelle : elle existe depuis un certain temps et vise à altérer le comportement du moteur de PHP. Elle n’est que peu connue, cela dit, parce que les directives existant actuellement ne sont que relativement peu utiles et utilisées. 

  4. J’arrive déjà à taper declare(strict_types=1) en n’ayant quasiment plus à réfléchir… Alors que je n’ai passé que quelques demi-heures à jouer avec !