Comme indiqué par le PO :
PHP traite tous les tableaux comme associatifs
il n'est pas tout à fait sensé (à mon humble avis) d'écrire une fonction qui vérifie si un tableau est associatif . Donc, première chose: qu'est-ce qu'une clé dans un tableau PHP ?:
La clé peut être soit un entier soit une chaîne .
Cela signifie qu'il y a 3 cas possibles:
- Cas 1. toutes les clés sont numériques / entières .
- Cas 2. toutes les clés sont des chaînes .
- Cas 3. certaines clés sont des chaînes , certaines clés sont numériques / entières .
Nous pouvons vérifier chaque cas avec les fonctions suivantes.
Cas 1: toutes les clés sont numériques / entières .
Remarque : Cette fonction renvoie également true pour les tableaux vides.
//! Check whether the input is an array whose keys are all integers.
/*!
\param[in] $InputArray (array) Input array.
\return (bool) \b true iff the input is an array whose keys are all integers.
*/
function IsArrayAllKeyInt($InputArray)
{
if(!is_array($InputArray))
{
return false;
}
if(count($InputArray) <= 0)
{
return true;
}
return array_unique(array_map("is_int", array_keys($InputArray))) === array(true);
}
Cas 2: toutes les clés sont des chaînes .
Remarque : Cette fonction renvoie également true pour les tableaux vides.
//! Check whether the input is an array whose keys are all strings.
/*!
\param[in] $InputArray (array) Input array.
\return (bool) \b true iff the input is an array whose keys are all strings.
*/
function IsArrayAllKeyString($InputArray)
{
if(!is_array($InputArray))
{
return false;
}
if(count($InputArray) <= 0)
{
return true;
}
return array_unique(array_map("is_string", array_keys($InputArray))) === array(true);
}
Cas 3. certaines clés sont des chaînes , certaines clés sont numériques / entières .
Remarque : Cette fonction renvoie également true pour les tableaux vides.
//! Check whether the input is an array with at least one key being an integer and at least one key being a string.
/*!
\param[in] $InputArray (array) Input array.
\return (bool) \b true iff the input is an array with at least one key being an integer and at least one key being a string.
*/
function IsArraySomeKeyIntAndSomeKeyString($InputArray)
{
if(!is_array($InputArray))
{
return false;
}
if(count($InputArray) <= 0)
{
return true;
}
return count(array_unique(array_map("is_string", array_keys($InputArray)))) >= 2;
}
Il s'ensuit que:
Maintenant, pour qu'un tableau soit un tableau "authentique" auquel nous sommes tous habitués, ce qui signifie:
- Ses clés sont toutes numériques / entières .
- Ses clés sont séquentielles (c'est-à-dire augmentant à l'étape 1).
- Ses clés partent de zéro .
Nous pouvons vérifier avec la fonction suivante.
Cas 3a. les clés sont numériques / entières , séquentielles et basées sur zéro .
Remarque : Cette fonction renvoie également true pour les tableaux vides.
//! Check whether the input is an array whose keys are numeric, sequential, and zero-based.
/*!
\param[in] $InputArray (array) Input array.
\return (bool) \b true iff the input is an array whose keys are numeric, sequential, and zero-based.
*/
function IsArrayKeyNumericSequentialZeroBased($InputArray)
{
if(!is_array($InputArray))
{
return false;
}
if(count($InputArray) <= 0)
{
return true;
}
return array_keys($InputArray) === range(0, count($InputArray) - 1);
}
Avertissements / pièges (ou, encore plus de faits particuliers sur les clés de tableau en PHP)
Touches entières
Les clés de ces tableaux sont des entiers :
array(0 => "b");
array(13 => "b");
array(-13 => "b"); // Negative integers are also integers.
array(0x1A => "b"); // Hexadecimal notation.
Touches de chaîne
Les clés de ces tableaux sont des chaînes :
array("fish and chips" => "b");
array("" => "b"); // An empty string is also a string.
array("stackoverflow_email@example.com" => "b"); // Strings may contain non-alphanumeric characters.
array("stack\t\"over\"\r\nflow's cool" => "b"); // Strings may contain special characters.
array('$tα€k↔øv∈rflöw⛄' => "b"); // Strings may contain all kinds of symbols.
array("functіon" => "b"); // You think this looks fine? Think again! (see https://stackoverflow.com/q/9246051/1402846)
array("ま말轉转ДŁ" => "b"); // How about Japanese/Korean/Chinese/Russian/Polish?
array("fi\x0sh" => "b"); // Strings may contain null characters.
array(file_get_contents("https://www.google.com/images/nav_logo114.png") => "b"); // Strings may even be binary!
Touches entières qui ressemblent à des chaînes
Si vous pensez que la clé array("13" => "b")
est une chaîne , vous vous trompez . Du doc ici :
Les chaînes contenant des entiers valides seront converties en type entier. Par exemple, la clé "8" sera stockée sous 8. En revanche, "08" ne sera pas converti, car il ne s'agit pas d'un entier décimal valide.
Par exemple, la clé de ces tableaux sont des entiers :
array("13" => "b");
array("-13" => "b"); // Negative, ok.
Mais la clé de ces tableaux sont des chaînes :
array("13." => "b");
array("+13" => "b"); // Positive, not ok.
array("-013" => "b");
array("0x1A" => "b"); // Not converted to integers even though it's a valid hexadecimal number.
array("013" => "b"); // Not converted to integers even though it's a valid octal number.
array("18446744073709551616" => "b"); // Not converted to integers as it can't fit into a 64-bit integer.
De plus, selon le doc ,
La taille d'un entier dépend de la plate-forme, bien qu'une valeur maximale d'environ deux milliards soit la valeur habituelle (c'est-à-dire 32 bits signés). Les plates-formes 64 bits ont généralement une valeur maximale d'environ 9E18, à l'exception de Windows, qui est toujours de 32 bits. PHP ne prend pas en charge les entiers non signés.
La clé de ce tableau peut donc être ou non un entier - cela dépend de votre plate-forme.
array("60000000000" => "b"); // Array key could be integer or string, it can fit into a 64-bit (but not 32-bit) integer.
Pire encore, PHP a tendance à être bogué si l'entier est proche de la frontière 2 31 = 2 147 483 648 (voir bogue 51430 , bogue 52899 ). Par exemple, sur mon environnement local (PHP 5.3.8 sur XAMPP 1.7.7 sur Windows 7), var_dump(array("2147483647" => "b"))
donne
array(1) {
[2147483647]=>
string(1) "b"
}
mais sur cette démo en direct sur codepad (PHP 5.2.5), la même expression donne
array(1) {
["2147483647"]=>
string(1) "b"
}
La clé est donc un entier dans un environnement mais une chaîne dans un autre, même s'il 2147483647
s'agit d'un entier 32 bits signé valide .