mb_convert_case
Converts a string to upper, lower, title or folded case using full Unicode case mapping.
mb_convert_case(string $string, int $mode, ?string $encoding = null): string- Added in PHP 4.3.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$string | string | The string being converted. |
$mode | int | One of MB_CASE_UPPER, MB_CASE_LOWER, MB_CASE_TITLE, MB_CASE_FOLD, or the *_SIMPLE variants MB_CASE_UPPER_SIMPLE, MB_CASE_LOWER_SIMPLE, MB_CASE_TITLE_SIMPLE and MB_CASE_FOLD_SIMPLE. |
$encodingoptional | ?string= null | The character encoding of the string. If omitted or null, the internal encoding is used. |
Return value
stringA case-converted copy of the string, in the same encoding.
Errors
Throws a ValueError if encoding is not a name mbstring recognises, or if mode is not one of the MB_CASE_* constants.
Changelog
- PHP 8.3.0Conditional casing rules for the Greek letter sigma were implemented; they apply to MB_CASE_LOWER and MB_CASE_TITLE but not to the _SIMPLE variants.
- PHP 7.3.0MB_CASE_FOLD, MB_CASE_UPPER_SIMPLE, MB_CASE_LOWER_SIMPLE, MB_CASE_TITLE_SIMPLE and MB_CASE_FOLD_SIMPLE were added as modes.
mb_convert_case() is the one case function in PHP that applies real Unicode case mapping. strtoupper() and ucwords() work byte by byte and leave anything above ASCII untouched, so strtoupper('élan') gives you éLAN. This function gives you ÉLAN.
The mode you pick matters more than people expect:
- MB_CASE_UPPER and MB_CASE_LOWER — full mappings, so a single character may become several (
ßuppercases toSS). - MB_CASE_TITLE — uppercases the first letter of each word and lowercases the rest, unlike
ucwords(), which only touches first letters. - MB_CASE_FOLD — not for display. Case folding produces a canonical form designed purely for case-insensitive comparison, so
StraßeandSTRASSEfold to the same string.
The _SIMPLE variants added in PHP 7.3 restrict themselves to one-character-in, one-character-out mappings. Use them only when a length or code-point-count guarantee matters more than correctness; for anything user-facing the full modes are what you want.
For comparison work, fold both sides and compare with ===. Never lowercase-and-compare with strtolower() on non-ASCII text — it will report two equal strings as different.
Example
When to use it
- Uppercase an accented or Cyrillic name for a printed label or shipping form.
- Title-case a product name typed entirely in caps by a data-entry operator.
- Compare two usernames case-insensitively when they may contain non-ASCII letters.
- Normalise search terms so a query for "STRASSE" matches stored text "Straße".
Frequently asked questions
What is the difference between mb_convert_case and mb_strtoupper?
mb_strtoupper() is a shortcut for mb_convert_case() with MB_CASE_UPPER and nothing else. mb_convert_case() additionally offers title case, case folding and the simple mapping variants.
How do I title case a UTF-8 string in PHP?
Use mb_convert_case($string, MB_CASE_TITLE, 'UTF-8'). Unlike ucwords() it capitalises words starting with accented or non-Latin letters, and it lowercases the remaining letters of each word.
When should I use MB_CASE_FOLD instead of MB_CASE_LOWER?
Use MB_CASE_FOLD whenever you are comparing strings rather than showing them, because folding normalises pairs such as ß and ss that lowercasing keeps distinct. Never render folded text to a user.
More examples
Title case that actually handles accents
ucwords() only capitalises "alles", because the first byte of "élan" and "über" is not an ASCII letter it knows how to change. MB_CASE_TITLE capitalises all three words, and on the third line it also lowercases the trailing letters — something ucwords() never does, since it leaves the rest of each word exactly as it found it.
<?php
$name = "élan über alles";
echo ucwords($name), "\n";
echo mb_convert_case($name, MB_CASE_TITLE, 'UTF-8'), "\n";
$shouty = "MÜNCHEN HAUPTBAHNHOF";
echo mb_convert_case($shouty, MB_CASE_TITLE, 'UTF-8'), "\n";Case-insensitive comparison with folding
strtolower() reports the two spellings as different, because it cannot map Ü and knows nothing about ß. Full case folding maps ß to ss and Ü to ü, so both strings collapse to "grüssen" and compare equal — the correct answer for a login or search lookup.
<?php
$a = "Grüßen";
$b = "GRÜSSEN";
var_dump(strtolower($a) === strtolower($b));
$fa = mb_convert_case($a, MB_CASE_FOLD, 'UTF-8');
$fb = mb_convert_case($b, MB_CASE_FOLD, 'UTF-8');
echo $fa, " / ", $fb, "\n";
var_dump($fa === $fb);Full versus simple mappings
The full mapping expands ß into SS, so the result is one character longer than the input. The _SIMPLE variant guarantees one character out per character in and therefore leaves ß unchanged. Pick _SIMPLE only when that length guarantee is what you need; otherwise the full mapping is the correct German uppercasing.
<?php
$s = "straße";
$full = mb_convert_case($s, MB_CASE_UPPER, 'UTF-8');
$simple = mb_convert_case($s, MB_CASE_UPPER_SIMPLE, 'UTF-8');
echo $full, " (", mb_strlen($full, 'UTF-8'), " chars)\n";
echo $simple, " (", mb_strlen($simple, 'UTF-8'), " chars)\n";
Discussion