En route vers PHP 5.5 : Déréférencement de constantes string et array

22 octobre 2012php, php-5.5
 Cet article a été rédigé il y a plusieurs années et peut ne plus être tout à fait à jour…

PHP permet d’utiliser [] pour accéder à un élément donné d’un tableau ou à un caractère précis d’une chaine de caractères.

Mais, jusqu’à PHP <= 5.4, [] ne pouvait être utilisé que sur une variable, et pas directement lors de la déclaration d’une chaine ou d’un array.

C’est maintenant chose possible, avec la branche master de PHP (et donc, probablement, avec PHP 5.5).

Quelques exemples de déréférencement de variables string / array

Comme premier exemple, essayons d’accèder à un caractère donné d’une chaine de caractères, en utilisant [] :

// Obtenir un caractère d'une chaine
var_dump( "php"[1] );     // 'h'

Avec la version courante de la branche master de PHP (et donc, probablement, PHP 5.5), exécuter cette portion de code vous donnera la sortie suivante :

string(1) "h"

Autrement dit, le déréférencement d’une constante de type chaine de caractères fonctionne – alors qu’en PHP <= 5.4, il vous aurait fallu stocker la chaine de caractères dans une variable.


L’idée qui vient ensuite est de faire exactement la même chose sur un tableau, que ce soit en le déclarant avec la syntaxe longue array() ou la syntaxe courte [] introduite par PHP 5.4 :

// Accéder à un élément d'un tableau
var_dump( array(1, 2, 3)[1] );  // 2
var_dump( [1, 2, 3][1] );  // 2

Et là encore, nous parvenons à accéder à l’élément ciblé de chacun de nos deux tableaux, sans avoir besoin de passer par des variables temporaires contenant ceux-ci :

int(2)
int(2)

Bien entendu, nous pouvons aussi tester sur un tableau à plusieurs dimensions :

// Avec un tableau à plusieurs dimensions
var_dump( [ ['hello', 'plop', 'glop'], [1, 2, 3] ] [0][1] );    // "plop"

Et là encore, nous obtenons le résultat attendu :

string(4) "plop"


Ici encore, il ne s’agit pas d’une nouvelle fonctionnalité révolutionnaire, mais d’un peu de sucre syntaxique supplémentaire, qui peut rendre notre code plus concis, plus agréable tant à lire qu’à écrire.

Les cas d’erreur restent les mêmes

Cette nouvelle possibilité syntaxique ne change pas les cas d’erreurs qui existaient déjà.

En particulier, les deux cas suivants :

// Ca, ça ne change pas (malgré la nouvelle syntaxe)
var_dump( "hello world"["hello"] );   // Illegal string offset 'hello' + 'h'
var_dump( [1, 2, 3][100] );  // Undefined offset: 100 + NULL

Continuent de mener à deux alertes :

Warning:  Illegal string offset 'hello' 
    in /.../php-5.5/tests/constdereference/constdereference-1.php on line 15
string(1) "h"

Notice:  Undefined offset: 100 
    in /.../php-5.5/tests/constdereference/constdereference-1.php on line 16
NULL

En quelques mots :

  • Dans le premier cas, "hello" n’est pas une position valide dans une chaine de caractères, ce qui explique le Warning – et "hello" converti en entier donne 0, ce qui explique que l’on obtienne le "h" comme affichage, puisqu’il s’agit du premier caractère de la chaine "hello world".
  • Et dans le second cas, essayer d’accéder à un élement inexistant d’un tableau continue bien entendu de lever une Notice.

Voir aussi

  • Bug #60408: Array/String element access on instantiation : une feature-request demandant l’implémentation de cette fonctionnalité (initialement, pour les tableaux ; elle a ensuite été mise à jour pour s’intéresser aussi aux chaines de caractères).
  • RFC: Const array/string dereference : la RFC correspondant à l’implémentation de la feature-request ; vous noterez que même si la fonctionnalité a été demandée alors que PHP 5.4 n’était pas encore sortie (la RFC date de fin novembre 2011, et PHP 5.4.0 de début mars 2012), le vote porte explicitement sur son inclusion sur le trunk de PHP, et pas sur la branche correspondant à la version 5.4 qui était en cours de préparation (comme quoi c’est chose qui arrive ;-) ).