Multibyte strings7 min readExamples run on PHP 8.5.10

mb_str_pad()

Learn how PHP 8.4 mb_str_pad() pads UTF-8 and other multibyte strings by codepoints, with its signature, return value, edge cases and mistakes.

Signature

mb_str_pad(
    string $string,
    int $length,
    string $pad_string = " ",
    int $pad_type = STR_PAD_RIGHT,
    ?string $encoding = null
): string

Purpose

mb_str_pad() makes a string reach a target length by adding padding on the left, the right, or both sides. It works like str_pad(), except that the length is counted in Unicode codepoints rather than bytes. This matters for text such as café, Åsa or Japanese names, where one visible character can take several bytes in UTF-8.

The manual lists the function as available from PHP 8.3.0, so it is also available in PHP 8.4.

Signature

Parameters and defaults

  • $string is the input text.
  • $length is the desired total length in codepoints. If it is negative, less than the input length, or equal to it, no padding happens and the original string is returned.
  • $pad_string is the text used for padding. It defaults to a single space. If the number of padding characters needed is not a multiple of its length, the last copy is cut short.
  • $pad_type is STR_PAD_RIGHT (the default), STR_PAD_LEFT or STR_PAD_BOTH.
  • $encoding names the character encoding. When omitted or null, PHP uses the current internal encoding. Passing 'UTF-8' explicitly makes your intent clear.

Return value and failure cases

The function returns the padded string. It never changes the original variable. When padding is not needed, you get the input back unchanged.

Invalid arguments are rejected with a ValueError. Examples are an empty $pad_string, an unsupported $pad_type, or an unknown encoding name. Check user-supplied padding strings and encodings before calling the function.

Example 1: all three padding modes

This uses symbols that are each three bytes in UTF-8, but each counts as one codepoint. The pad string is longer than the space available, so it is repeated and truncated as needed.

Example
<?php
echo json_encode([
    mb_str_pad('▶▶', 6, '❤❓❇', STR_PAD_RIGHT),
    mb_str_pad('▶▶', 6, '❤❓❇', STR_PAD_LEFT),
    mb_str_pad('▶▶', 6, '❤❓❇', STR_PAD_BOTH),
], JSON_UNESCAPED_UNICODE);
echo "\n";
Output
["▶▶❤❓❇❤","❤❓❇❤▶▶","❤❓▶▶❤❓"]

With STR_PAD_BOTH, four padding characters are split evenly, two on each side.

Example 2: why str_pad() is not enough

In UTF-8, é takes two bytes. str_pad() sees café as five bytes and adds only two stars to reach seven. mb_str_pad() sees four characters and adds three.

Example
<?php
$name = 'café';
echo json_encode([
    'bytePad' => str_pad($name, 7, '*'),
    'mbPad' => mb_str_pad($name, 7, '*', STR_PAD_RIGHT, 'UTF-8'),
], JSON_UNESCAPED_UNICODE);
echo "\n";
Output
{"bytePad":"café**","mbPad":"café***"}

Example 3: aligning a plain-text list

A fixed-width report is a typical use. The names are padded on the right and the counts on the left, so the columns line up even with accented letters.

Example
<?php
$rows = [['Zoë', '4'], ['Åsa', '12'], ['Li', '7']];
foreach ($rows as [$name, $count]) {
    echo mb_str_pad($name, 6, '.', STR_PAD_RIGHT, 'UTF-8'),
        mb_str_pad($count, 3, ' ', STR_PAD_LEFT, 'UTF-8'), "\n";
}
Output
Zoë...  4
Åsa... 12
Li....  7

Every line has the same number of codepoints, so a monospaced font shows aligned columns.

Edge cases

  • Target not larger than input: a $length that is equal, smaller or negative returns the string untouched.
  • Uneven centering: with STR_PAD_BOTH, an odd amount of padding cannot be split equally. The left side gets the smaller half and the right side gets the remainder, which matches the familiar str_pad() behavior.
  • Truncated padding: a multi-character $pad_string may be cut in the middle of its sequence when the available space is not a multiple of its length.
  • Codepoints are not glyphs: the length is a codepoint count. An emoji built from several codepoints, or a letter plus a combining accent, counts as more than one unit even if it looks like one symbol. Likewise, wide East Asian characters may take more screen width than their count suggests.
  • Encoding mismatch: if the string is not valid in the chosen encoding, the result may not be what you expect. Keep your data and the $encoding argument consistent.

Common mistakes

  1. Using str_pad() for non-ASCII text and getting misaligned output because it counts bytes.
  2. Assuming $length is the number of characters to add. It is the final total length.
  3. Passing an empty pad string and not handling the resulting ValueError.
  4. Expecting visual width rather than codepoint count, especially for emoji sequences or combining marks.
  5. Forgetting that the function returns a new string, so the result must be assigned or output.
  • str_pad() pads by bytes and suits ASCII or binary data.
  • mb_strlen() counts codepoints and helps you compute your own widths.
  • mb_strwidth() estimates display width for wide characters.
  • mb_substr() and mb_strimwidth() shorten text before or instead of padding.
  • mb_internal_encoding() reads or sets the default encoding used when $encoding is null.

Recap

Use mb_str_pad() when the target length should be measured in characters rather than bytes. Remember the defaults (a space and right padding), the no-op rule for short targets, the possible truncation of the pad string, and the ValueError for invalid arguments. For exact on-screen alignment, remember that codepoints are not always the same as display width.

Tested examples

All three padding modes with multibyte symbols
<?php
echo json_encode([
    mb_str_pad('▶▶', 6, '❤❓❇', STR_PAD_RIGHT),
    mb_str_pad('▶▶', 6, '❤❓❇', STR_PAD_LEFT),
    mb_str_pad('▶▶', 6, '❤❓❇', STR_PAD_BOTH),
], JSON_UNESCAPED_UNICODE);
echo "\n";
Output
["▶▶❤❓❇❤","❤❓❇❤▶▶","❤❓▶▶❤❓"]
Byte-based str_pad() versus mb_str_pad()
<?php
$name = 'café';
echo json_encode([
    'bytePad' => str_pad($name, 7, '*'),
    'mbPad' => mb_str_pad($name, 7, '*', STR_PAD_RIGHT, 'UTF-8'),
], JSON_UNESCAPED_UNICODE);
echo "\n";
Output
{"bytePad":"café**","mbPad":"café***"}
Aligning a plain-text list
<?php
$rows = [['Zoë', '4'], ['Åsa', '12'], ['Li', '7']];
foreach ($rows as [$name, $count]) {
    echo mb_str_pad($name, 6, '.', STR_PAD_RIGHT, 'UTF-8'),
        mb_str_pad($count, 3, ' ', STR_PAD_LEFT, 'UTF-8'), "\n";
}
Output
Zoë...  4
Åsa... 12
Li....  7