array_change_key_case
Returns a copy of an array with all string keys converted to lower or upper case.
array_change_key_case(array $array, int $case = CASE_LOWER): array- Added in PHP 4.2.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$array | array | The array whose keys should be converted. |
$caseoptional | int= CASE_LOWER | Either CASE_LOWER (the default) or CASE_UPPER. |
Return value
arrayA copy of the array with every string key converted to the requested case. Integer keys are returned unchanged.
Conversion is plain byte-wise ASCII casing, independent of locale. Only the ASCII letters of a key are converted; bytes outside A–Z/a–z are left untouched, so the accented characters — not the whole key — survive: ÉTAT comes back as État and Straße as straße under CASE_LOWER. Convert those yourself with mb_convert_case() over array_keys() and rebuild with array_combine().
Example
When to use it
- Normalise HTTP header names before looking up 'content-type'
- Lower-case CSV header columns so row lookups do not depend on the exporter's capitalisation
- Make config arrays merged from .env, .ini and defaults use one consistent key case
Frequently asked questions
Does array_change_key_case work on nested arrays?
No, it only converts keys at the top level of the array. Values that are themselves arrays are copied as-is with their original keys, so you need a small recursive function if you want the whole structure normalised.
Why are my numeric keys not changing?
Numeric keys are integers, and integers have no case. The function deliberately leaves them exactly as they are, including string keys such as '20' that PHP has already converted to the integer 20.
Does array_change_key_case handle accented or UTF-8 keys?
Not reliably — it applies plain ASCII case conversion, so only the ASCII letters of a key are changed and non-ASCII bytes are left as they are: 'ÉTAT' comes back as 'État', not unchanged and not fully lower-cased. For multibyte keys, map mb_convert_case() over array_keys() and rebuild the array with array_combine().
More examples
Numeric keys are left alone
The output shows only 'Name' and 'ID' were rewritten to 'name' and 'id'. The key 10 and the string '20' are both stored as integers, so the function skips them entirely — casing only applies to string keys.
<?php
$mixed = ['Name' => 'Ada', 10 => 'ten', 'ID' => 42, '20' => 'twenty'];
var_dump(array_change_key_case($mixed, CASE_LOWER));Colliding keys silently overwrite
All three keys become 'key', so only the last value survives: the result is one entry with 'third'. Count the array before and after when the source may contain near-duplicate keys.
<?php
$input = ['keY' => 'first', 'Key' => 'second', 'KEY' => 'third'];
$out = array_change_key_case($input, CASE_LOWER);
print_r($out);
echo "kept ", count($out), " of ", count($input), " entries\n";Making it recursive
The built-in only touches the outer level, so the nested HOST/PORT keys would normally survive as-is. This four-line wrapper walks into every sub-array, and the output shows db.host and db.port fully lower-cased.
<?php
function keysToLower(array $a): array {
$a = array_change_key_case($a, CASE_LOWER);
foreach ($a as $k => $v) {
if (is_array($v)) { $a[$k] = keysToLower($v); }
}
return $a;
}
print_r(keysToLower(['DB' => ['HOST' => 'localhost', 'PORT' => 5432], 'Debug' => true]));
Discussion