Signature
mb_lcfirst(string $string, ?string $encoding = null): stringPurpose
mb_lcfirst() returns a copy of a string in which the first character is converted to lowercase. It is the multibyte-aware counterpart of lcfirst(). It was added in PHP 8.4 and belongs to the mbstring extension, so that extension must be enabled.
The word character matters. In UTF-8, a letter such as É takes more than one byte. A byte-oriented function cannot reliably treat it as a single unit, while mb_lcfirst() reads the string using a character encoding and changes the whole first character.
Signature
Parameters and defaults
$string: the input string. Only its first character is considered; the rest is copied unchanged.$encoding: the character encoding of the string, such as"UTF-8". If you omit it or passnull, PHP uses the current internal encoding of the mbstring extension.
Passing the encoding explicitly makes the code independent of global configuration, which is useful in libraries and in code that other people will copy.
Return value and failure cases
The function always returns a string. If the first character has no lowercase form (a digit, a space, punctuation, or a character that is already lowercase), the result is the same as the input. An empty string produces an empty string.
If you pass an encoding name that mbstring does not recognise, PHP throws a ValueError. Wrap dynamic encoding names in a try/catch block if they come from outside your program.
Example 1: multibyte versus ASCII-only
The first example compares mb_lcfirst() with plain lcfirst() on a word that begins with an accented capital letter. Plain lcfirst() does not handle this letter as a multibyte character, so it leaves the word unchanged, while mb_lcfirst() lowers it.
$word = "Élan";
echo json_encode([mb_lcfirst($word, "UTF-8"), lcfirst($word)], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";["élan","Élan"]
Example 2: mapping over a list
Because the function takes a string and returns a string, it fits naturally into array_map(). The list below includes an empty string and a value starting with a digit to show that neither causes trouble.
$labels = ["Ärger", "Öl", "Zebra", "", "123Abc"];
$result = array_map(fn(string $s): string => mb_lcfirst($s, "UTF-8"), $labels);
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";["ärger","öl","zebra","","123Abc"]
Example 3: only the first character changes
This example shows that the rest of the string is left alone, and that an invalid encoding name raises a ValueError.
$result = mb_lcfirst("ÉCOLE", "UTF-8");
try {
mb_lcfirst("Abc", "not-an-encoding");
$error = "none";
} catch (ValueError $e) {
$error = get_class($e);
}
echo json_encode([$result, $error], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";["éCOLE","ValueError"]
Edge cases
- Empty input: returns
"". - No lowercase form: digits, punctuation and whitespace at the start are returned unchanged.
- Already lowercase: the string is returned as it was.
- Leading whitespace: if the string begins with a space, the first character is the space, so nothing is lowercased. Trim first if that is not what you want.
- Wrong encoding: if the bytes are not valid in the declared encoding, the result may not be meaningful. Make sure the encoding matches the actual data.
Common mistakes
- Expecting the whole string to change.
mb_lcfirst()is notmb_strtolower(). If you need every character lowercased, usemb_strtolower(). - Using
lcfirst()on UTF-8 text. It works on bytes, so it will not lower a non-ASCII first letter such asÉ. - Relying on the default encoding. If the internal encoding is changed elsewhere, your output can change too. Pass
"UTF-8"explicitly when you know the data is UTF-8. - Forgetting that the function returns a new string. The original variable is not modified; assign the result.
- Passing untrusted encoding names. An unknown name throws
ValueError, so validate such input first.
Related functions
mb_ucfirst(): makes the first character uppercase, the opposite operation.lcfirst(): the byte-based version of this operation.mb_strtolower(): lowercases an entire multibyte string.mb_substr(): extracts characters by position when you need custom logic.
Recap
Use mb_lcfirst($string, "UTF-8") when you want to lowercase just the first character of text that may contain non-ASCII letters. It returns a string, leaves everything after the first character untouched, returns empty input as empty, and throws ValueError for unknown encoding names.
Tested examples
$word = "Élan";
echo json_encode([mb_lcfirst($word, "UTF-8"), lcfirst($word)], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
["élan","Élan"]
$labels = ["Ärger", "Öl", "Zebra", "", "123Abc"];
$result = array_map(fn(string $s): string => mb_lcfirst($s, "UTF-8"), $labels);
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
["ärger","öl","zebra","","123Abc"]
$result = mb_lcfirst("ÉCOLE", "UTF-8");
try {
mb_lcfirst("Abc", "not-an-encoding");
$error = "none";
} catch (ValueError $e) {
$error = get_class($e);
}
echo json_encode([$result, $error], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
["éCOLE","ValueError"]