mb_str_split
Splits a string into an array of characters or fixed-size chunks without breaking multibyte characters.
mb_str_split(string $string, int $length = 1, ?string $encoding = null): array- Added in PHP 7.4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$string | string | The string to split. |
$lengthoptional | int= 1 | Number of characters per chunk. Must be 1 or greater. |
$encodingoptional | ?string= null | Character encoding. Null uses the internal encoding. |
Return value
arrayAn array of the chunks. An empty input string yields an empty array.
Errors
Throws a ValueError if length is less than 1, or if encoding is not a valid encoding.
Changelog
- PHP 8.0.0encoding is nullable now.
- PHP 8.0.0This function no longer returns false on failure; an invalid length now throws a ValueError instead.
mb_str_split() turns a string into an array whose elements are whole characters, or chunks of length characters. It is the fix for str_split(), which slices by byte and will happily hand you back half of a é — an invalid fragment that breaks json_encode() and prints as a replacement glyph.
When to reach for it
Use it whenever you need per-character access to text that is not guaranteed ASCII: reversing a string, counting character frequencies, shuffling or masking, spelling out an input one glyph at a time, or chunking a message into fixed-size pieces for a protocol that counts characters. It is also the readable way to loop over characters — foreach (mb_str_split($s) as $ch) beats a manual mb_substr() loop, which is O(n²) on long strings.
What trips people up
It splits by codepoint, not by grapheme. A flag emoji, a skin-tone modifier or a base letter followed by a combining accent is several codepoints, so mb_str_split() tears the glyph apart. For user-visible "characters" use grapheme_str_split() from the intl extension instead.
The final chunk is short when the length does not divide evenly, and the array is always a list with sequential integer keys.
Example
When to use it
- Reverse a UTF-8 string safely by splitting, reversing the array and imploding
- Count how often each character appears in non-ASCII text with array_count_values
- Break a message into fixed 70-character chunks for an SMS or a fixed-width protocol
- Mask all but the last four characters of an account identifier
Frequently asked questions
What is the difference between str_split and mb_str_split?
str_split splits by bytes and mb_str_split splits by characters. On any input containing multibyte characters str_split produces invalid fragments, so use mb_str_split for UTF-8 text.
Does mb_str_split handle emoji correctly?
Only for single-codepoint emoji. Emoji with skin tones, flags or zero-width-joiner sequences span several codepoints and get split apart; use grapheme_str_split() from intl if you need whole visible glyphs.
What PHP version added mb_str_split?
PHP 7.4.0. Before 8.0 it returned false on failure; since 8.0 it throws a ValueError for an invalid length or encoding instead.
More examples
Reverse a multibyte string
The first line prints 'eßürG'. The second shows why strrev() is unusable here: it reverses bytes, so the two-byte sequences for ü and ß come out backwards and the output is mojibake.
<?php
mb_internal_encoding('UTF-8');
$s = 'Grüße';
echo implode('', array_reverse(mb_str_split($s))), "\n";
echo strrev($s), "\n";Character frequency count
array_count_values works on the character array directly, giving a=2, b=2, c=1, é=1 and four distinct characters. Doing the same with str_split would report the two bytes of é as separate entries and inflate the count to five.
<?php
mb_internal_encoding('UTF-8');
$text = 'ababcé';
$counts = array_count_values(mb_str_split($text));
arsort($counts);
print_r($counts);
echo "distinct characters: ", count($counts), "\n";
Discussion