As stated by the OP:
PHP treats all arrays as associative
it is not quite sensible (IMHO) to write a function that checks if an array is associative. So first thing first: what is a key in a PHP array?:
The key can either be an integer or a string.
That means there are 3 possible cases:
- Case 1. all keys are numeric / integers.
- Case 2. all keys are strings.
- Case 3. some keys are strings, some keys are numeric / integers.
We can check each case with the following functions.
Case 1: all keys are numeric / integers.
Note: This function returns true for empty arrays too.
//! 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);
}
Case 2: all keys are strings.
Note: This function returns true for empty arrays too.
//! 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);
}
Case 3. some keys are strings, some keys are numeric / integers.
Note: This function returns true for empty arrays too.
//! 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;
}
It follows that:
Now, for an array to be a "genuine" array that we are all accustomed to, meaning:
- Its keys are all numeric / integers.
- Its keys are sequential (i.e. increasing by step 1).
- Its keys start from zero.
We can check with the following function.
Case 3a. keys are numeric / integers, sequential, and zero-based.
Note: This function returns true for empty arrays too.
//! 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);
}
Caveats / Pitfalls (or, even more peculiar facts about array keys in PHP)
Integer keys
The keys for these arrays are integers:
array(0 => "b");
array(13 => "b");
array(-13 => "b"); // Negative integers are also integers.
array(0x1A => "b"); // Hexadecimal notation.
String keys
The keys for these arrays are strings:
array("fish and chips" => "b");
array("" => "b"); // An empty string is also a string.
array("[email protected]" => "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://mcmap.net/q/54622/-how-do-i-fix-this-missing-semicolon-syntax-error-in-javascript/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!
Integer keys that look like strings
If you think the key in array("13" => "b")
is a string, you are wrong. From the doc here:
Strings containing valid integers will be cast to the integer type. E.g. the key "8" will actually be stored under 8. On the other hand "08" will not be cast, as it isn't a valid decimal integer.
For example, the key for these arrays are integers:
array("13" => "b");
array("-13" => "b"); // Negative, ok.
But the key for these arrays are strings:
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.
What's more, according to the doc,
The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). 64-bit platforms usually have a maximum value of about 9E18, except for Windows, which is always 32 bit. PHP does not support unsigned integers.
So the key for this array may or may not be an integer - it depends on your platform.
array("60000000000" => "b"); // Array key could be integer or string, it can fit into a 64-bit (but not 32-bit) integer.
Even worse, PHP tends to be buggy if the integer is near the 231 = 2,147,483,648 boundary (see bug 51430, bug 52899). For example, on my local environment (PHP 5.3.8 on XAMPP 1.7.7 on Windows 7), var_dump(array("2147483647" => "b"))
gives
array(1) {
[2147483647]=>
string(1) "b"
}
but on this live demo on codepad (PHP 5.2.5), the same expression gives
array(1) {
["2147483647"]=>
string(1) "b"
}
So the key is an integer in one environment but a string in another, even though 2147483647
is a valid signed 32-bit integer.
if (isset($array[0]))
, which is simple and fast. Of course, you should first be sure the array isn't empty, and you should have some knowledge on the possible contents of the array so that the method couldn't fail (like mixed numeric/associative, or non-sequential). – Tyrusarray_is_list
: https://mcmap.net/q/53406/-how-to-check-if-php-array-is-associative-or-sequential – Brunner