RFC: Using objects as keys

Voici une RFC qui avait été évoquée pendant les discussions à propos de UString : Using objects as keys.

L’idée de cette RFC était de permettre (de façon détournée) à des objets d’être utilisés comme clefs de tableaux — les tableaux PHP ne supportant en interne, comme clefs, que des entiers ou des chaînes.

Pour cela, une nouvelle méthode magique (qui pourrait être nommée __hash() — le nom proposé n’étant pas nécessairement définitif) serait mise en place : elle serait appelée lorsque l’on essayerait d’utiliser un objet comme clef d’un tableau, pour retourner la chaîne de caractères ou l’entier à réellement employer.

Par exemple, il deviendrait possible d’écrire quelque chose de ce type :

$obj = new MaClasse(); // implémentant une méthode __hash()
$arr = [];
$arr[$obj] = /* ici, quelque chose stocké dans le tableau, à l'index $obj->hash() */
Exemple

Les votes se sont tenus entre le 16 décembre 2014 et le 6 janvier 2015 et requéraient une majorité de 2/3. Nous avons exprimé notre opinion, défavorable du fait que cette proposition n’aille pas assez loin, sur internals@.
Cette proposition a été rejetée à 24 voix contre 6.

RFC: PHP 5.7

Le but de la RFC PHP 5.7 était de créer la version susnommée afin de simplifier la transition vers la version 7 qui avait été actée.
Il était prévu pour cette version mineure de générer des avertissements E_DEPRECATED pour les fonctionnalités dépréciées ainsi que réserver des mots-clefs introduits par PHP 7. Celle-ci n’apporterait aucune nouvelle fonctionnalité.

Nous avons, pour la majorité, été convaincu par les deux principaux arguments de cette RFC :

  • les applications pouvaient aisément résoudre les problèmes de compatibilité apportés par PHP 7 avant même que celle-ci soit officiellement disponible, accélérant ainsi son adoption
  • l’ajout d’une année supplémentaire au support de PHP 5, qui se termine actuellement en août 2017, aurait permis d’assurer à la version PHP 5 des correctifs, notamment de sécurité, jusqu’en 2018.

Confrontée aux statistiques d’utilisations de PHP proposées par Pascal Martin, des arguments contraires se sont toutefois fait entendre à l’encontre de cette RFC. En effet, il apparaît que les deux versions PHP les plus utilisées aujourd’hui sont PHP 5.2 et PHP 5.3 ; l’ajout d’une version 5.7 n’aurait donc eu vraisemblablement que peu d’incidence sur l’adoption de PHP 7.

Nous avons donc donné un avis relativement partagé sur internals@, précisant que le plus important restait toutefois la sortie de PHP 7.

La RFC a été rejetée par 19 voix contre 14, car pour l’heure, PHP 7 n’intègre pas suffisamment de problèmes de rétrocompatibilité pour justifier une version 5.7.
Néanmoins, les échanges sur internals@ ont laissé entendre que si des RFC générant des problèmes majeurs de rétrocompatibilité venaient à être intégrées au périmètre de PHP 7, une RFC à propos de PHP 5.7 pourrait se voir offrir une seconde chance et un nouveau vote.

RFC: Unicode Codepoint Escape Syntax

Cette RFC proposait de permettre l’utilisation de séquences Unicode dans les chaînes de caractères (à double-guillemets et heredoc) de PHP.

$str = "Un caractère unicode : \u{1F602}";
Exemple

La RFC proposait d’autres exemples et expliquait pourquoi il avait été choisi de positionner { et } autour du code du caractère : lisibilité et pas de limite en dur au nombre de caractères attendus pour spécifier le code.

Les votes se sont tenus du 8 décembre 2014 au 18 décembre 2014 et nous avons exprimé notre opinion positive sur internals@.
La RFC a été adoptée à 23 voix contre 2.

RFC: ZPP Failure on Overflow

Aujourd’hui, lorsqu’un nombre flottant trop grand pour tenir dans les valeurs supportées pour les entiers est passé en paramètre d’une fonction interne (fonction exposée par PHP ou une extension PHP) qui attend un entier, il est reçu par la fonction sous la forme… d’un entier… ce qui entraîne une perte d’information.

Note technique : une fonction interne spécifie de quel type (au sens C du terme, donc avec du typage strict) chaque paramètre reçu doit être. Il n’y a pas, en C, de type fourre-tout comme c’est le cas pour les variables de PHP, avec utilisation automatique de flottants lorsque des nombres sont trop grands pour tenir sur des entiers.

Cette RFC proposait donc que, dans le cas où un paramètre entier est attendu et que la valeur reçue est un flottant trop grand pour tenir dans un entier, l’analyse des paramètres de la fonction interne appelée échoue, que la fonction retourne sans s’exécuter, et qu’un avertissement soit levé.

Impact pour les utilisateurs de PHP : appeler une fonction interne attendant un entier en passant une valeur trop grande pour tenir dans un entier entraînera la levée d’un avertissement et la non-exécution de la fonction — au lieu de son exécution avec une valeur tronquée.

Cette RFC visait la version 7 de PHP.

Les votes ont été ouverts le 2 Décembre 2014 et on été clos le 12 décembre 2014. Cette RFC touchant plus à de l’implémentation qu’à des fonctionnalités, nous avons timidement exprimé notre opinion sur internals@, en considérant qu’il valait mieux un avertissement clair qu’un comportement étrange.
La RFC a été adoptée à l’unanimité (16 pour, 0 contre).

RFC: Static classes

La RFC Static classes partait du constat qu’il est aujourd’hui possible de créer des classes avec propriétés et méthodes statiques uniquement, mais qu’il est impossible de les définir comme non instanciables sans passer par un constructeur privé, ce qui rend notamment ces classes non testable.

Le but de cette RFC était d’ajouter un mot clef static au niveau de la classe afin de définir l’intégralité de son comportement comme tel :

static class Environment
{
    private $rootDirectory = '/var/www/project';
    public function getRootDirectory()
    {
        return self::$rootDirectory;
    }
}

Notons toutefois qu’aujourd’hui, un tel comportement est presque possible en utilisant une classe abstraite :

abstract class Environment
{
    static private $rootDirectory = '/var/www/project';
    static public function getRootDirectory()
    {
        return self::$rootDirectory;
    }
}

Néanmoins, cette syntaxe présente plusieurs limites que la RFC souhaitait couvrir :

  • il est possible d’oublier un mot-clef static
  • la classe peut être étendue et donc instanciée par le biais d’une classe fille, la rendant non statique : il faudrait y ajouter le mot clef final.

C’est pour cette raison que la RFC fut lancée sous le nom de Abstract Final class. Le but premier était de donner la possibilité de rendre une classe abstraite finale.

Le principe fut rejeté car une classe abstraite a pour but même d’être étendue alors qu’une classe finale ne peut pas l’être !
C’est pour cette raison qu’après moult échanges en interne, la RFC fut proposée une nouvelle fois sous son nouveau nom, afin d’ajouter un nouveau mot clef pour lever toute incompréhension.

S’il est vrai que définir une classe comme statique dès sa déclaration à l’avantage indéniable de clarifier son rôle, il est toutefois ressorti de nos échanges qu’il semblerait que la plupart des cas d’utilisation étaient des collections de fonctions, parfois appelées helpers. La majorité fut contre cette demande, principalement car les classes statiques ne sont pas reconnues comme une pratique à encourager. Nous avons donc posté en ce sens sur internals@.

La RFC a été rejetée par 12 voix contre 5. Toutefois,  même si cette proposition voulait couvrir un périmètre plus large, le chargement automatique des fonctions est un sujet qui est ressorti plusieurs fois au cours de nos discussions. Un souhait visiblement partagé par de nombreux développeurs.

RFC: Filtered unserialize()

Cette RFC partait de l’idée que la dé-sérialisation de données n’est pas sûre, puisqu’il est, dans certains cas, possible d’injecter du code qui pourrait être automatiquement exécuté (par le destructeur de classe, par exemple) — bien sûr, cela suppose qu’on essaye de dé-sérialiser des données provenant d’une source non réellement sûre (ce que font probablement certaines applications).

Elle proposait donc de modifier la fonction unserialize() de PHP pour permettre d’interdire la dé-sérialisation d’objets ou de limiter celle-ci à un ensemble de classes listées.

Dans le cas où on essayerait de dé-sérialiser un objet non autorisé, on obtiendrait en retour une instance de classe incomplète, comme lorsqu’on essaye de dé-sérialiser un objet dont la classe n’existe pas.

Exemples :

// ceci va tout dé-sérialiser comme auparavant
$data = unserialize($foo);
// Ceci va convertir tous les objets en objets __PHP_Incomplete_Class
$data = unserialize($foo, ["allowed_classes" => false]);
// Ceci va convertir tous les objets à l'exception des instances de MyClass et de MyClass2 en objets __PHP_Incomplete_Class
$data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]);
// Ceci va accepter toutes les classes comme étant par défaut
$data = unserialize($foo, ["allowed_classes" => true]);

Les votes ont été ouverts le 3 novembre 2014 et ont été clos le 10 novembre 2014. Considérant qu’apporter un niveau de sécurité lors de la dé-sérialisation de données ne pouvait être que bénéfique, nous avons posté en ce sens sur internals@.
Cette RFC a été adoptée par 17 votes contre 6.

RFC: Safe Casting Functions

Cette RFC partait du constat que les opérateurs de transtypage existant, explicites, n’échouent jamais et ne lèvent jamais d’erreur — ce qui peut être dangereux (surtout s’ils sont utilisés sur des saisies utilisateurs), puisqu’ils retourneront un peu n’importe quoi si les données sur lesquelles on les utilise correspondent elles-mêmes à un peu n’importe quoi.

Elle proposait donc d’ajouter trois fonctions, qui auraient validé leur entrée, au lieu de transtyper aveuglément. Initialement, elles auraient retourné false en cas d’erreur (ce retour aurait pu être soumis à un vote complémentaire) :

  • to_int() : n’aurait accepté que des entiers, des flottants contenant des entiers et pouvant être représentés par des entiers, ou des chaînes contenant la représentation textuelle d’entiers.
  • to_float() : n’aurait accepté que des flottants, des entiers et des chaînes représentant des flottants.
  • to_string() : n’aurait accepté que des chaînes, des entiers, des flottants et des objets transtypables en chaînes.

La RFC entre plus en détail sur le pourquoi de pas mal de choix et donne un long tableau d’exemples.

Les votes ont été ouverts le 19 novembre 2014 et ont été clos le 29 novembre 2014. Nous avons posté un timide +0.5 sur internals@, en considérant que ces fonctions n’allaient pas assez loin vers un réel typage plus strict.
Cette RFC a finalement été rejetée par 16 votes contre 5.