Multibyte strings7 min readExamples run on PHP 8.5.10

mb_ltrim()

Learn how PHP 8.4 mb_ltrim() removes Unicode whitespace or custom characters from the start of a string, with examples, edge cases and common mistakes.

Signature

mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string
Available since PHP 8.4.07.48.08.18.28.38.48.5All versions →

Purpose

mb_ltrim() removes characters from the beginning of a string and leaves the rest untouched. It is the multibyte-aware counterpart of ltrim(). The older function works on bytes, so it cannot recognise a character such as the ideographic space (U+3000) or an arrow symbol. mb_ltrim() reads the input as characters in a given encoding, so these can be stripped safely. The function is available as of PHP 8.4.

Signature

Parameters and defaults

  • $string is the input text.
  • $characters is optional and defaults to null. With null, the function strips a built-in set of whitespace characters. That set includes the ASCII space, tab, line feed, carriage return, NUL byte, vertical tab and form feed. It also includes Unicode spaces such as the no-break space (U+00A0), the en and em spaces (U+2000 to U+200A), the line and paragraph separators (U+2028, U+2029), the ideographic space (U+3000), NEL (U+0085) and the Mongolian vowel separator (U+180E).
  • If you pass a string, it is a list of characters to strip. Each character is considered individually, and the order of the list does not matter.
  • $encoding is optional and defaults to null. When omitted or null, PHP uses the current internal encoding, which is UTF-8 unless your configuration says otherwise. Pass a name such as 'UTF-8' to make the call independent of that setting.

Return value and failures

The function always returns a string. If nothing at the start matches, you get the original text back. If every character matches, you get an empty string. An encoding name that PHP does not recognise is rejected with an error, so pass only supported names. Passing a custom $characters list replaces the default whitespace set rather than adding to it.

Example 1: Unicode whitespace that ltrim() misses

The string below starts with an ideographic space, a no-break space and two ordinary spaces. The multibyte function removes all four. The byte-based ltrim() stops at the first byte, which is not an ASCII space, so the string keeps its full 12-byte length.

Example
<?php
$text = "\u{3000}\u{00A0}  Hello";
$trimmed = mb_ltrim($text);
echo json_encode([
    'mb' => $trimmed,
    'mbLength' => mb_strlen($trimmed),
    'ltrimLength' => strlen(ltrim($text)),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
{"mb":"Hello","mbLength":5,"ltrimLength":12}

Example 2: A custom character list

When you supply $characters, only those characters are removed. The default whitespace is no longer included, so add a space to the list if you want it stripped too.

Example
<?php
$label = "\u{2192}\u{2192} Menu";
echo json_encode([
    'onlyArrows' => mb_ltrim($label, "\u{2192}"),
    'arrowsAndSpace' => mb_ltrim($label, "\u{2192} "),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
{"onlyArrows":" Menu","arrowsAndSpace":"Menu"}

Example 3: Only the start is changed

Trailing whitespace is preserved. Use mb_rtrim() or mb_trim() when you need the end handled as well. Passing null for $characters keeps the default set while still letting you name the encoding.

Example
<?php
$value = "  \u{00E9}t\u{00E9}  ";
echo json_encode([
    'trailingKept' => mb_ltrim($value, null, 'UTF-8'),
    'allWhitespace' => mb_ltrim("\u{2003}\u{2003}"),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
{"trailingKept":"été  ","allWhitespace":""}

Edge cases

  • An empty input string returns an empty string.
  • A string made only of strippable characters becomes ''.
  • Characters in the middle of the text are never touched, even if they appear in the list.
  • Passing an empty string as $characters means there is nothing to strip, so the input comes back unchanged. Do not confuse this with null, which selects the default whitespace set.
  • The input must be valid in the chosen encoding. Text in a different encoding from the one you declare can give unexpected results, so keep the declared encoding and the real data consistent.

Common mistakes

  1. Treating $characters as a prefix. mb_ltrim('abcabcX', 'abc') does not remove one abc. It removes every leading character that is a, b or c, and stops at X.
  2. Expecting default whitespace to survive a custom list. Once you pass your own list, spaces are kept unless you include them.
  3. Using ltrim() for Unicode text. Byte-oriented trimming will not remove spaces such as U+3000 or U+2003 unless you list their raw bytes, and doing so risks cutting into a multibyte sequence.
  4. Expecting both ends to be trimmed. The function only affects the start of the string.
  5. Relying on a server-wide internal encoding. If your code must behave identically everywhere, pass the encoding explicitly.
  6. Using it on PHP versions before 8.4. The function does not exist there, so guard it with function_exists() or require PHP 8.4 or later.
  • mb_trim() strips from both ends.
  • mb_rtrim() strips from the end only.
  • ltrim() is the byte-based version for the start of a string.

Recap

Use mb_ltrim() to remove leading whitespace or a chosen set of characters from text that may contain multibyte characters. The default set covers many Unicode spaces. A custom list replaces that default and is treated as a set of individual characters. The return value is always a string.

Tested examples

Unicode whitespace that ltrim() misses
<?php
$text = "\u{3000}\u{00A0}  Hello";
$trimmed = mb_ltrim($text);
echo json_encode([
    'mb' => $trimmed,
    'mbLength' => mb_strlen($trimmed),
    'ltrimLength' => strlen(ltrim($text)),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
{"mb":"Hello","mbLength":5,"ltrimLength":12}
A custom character list
<?php
$label = "\u{2192}\u{2192} Menu";
echo json_encode([
    'onlyArrows' => mb_ltrim($label, "\u{2192}"),
    'arrowsAndSpace' => mb_ltrim($label, "\u{2192} "),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
{"onlyArrows":" Menu","arrowsAndSpace":"Menu"}
Only the start is changed
<?php
$value = "  \u{00E9}t\u{00E9}  ";
echo json_encode([
    'trailingKept' => mb_ltrim($value, null, 'UTF-8'),
    'allWhitespace' => mb_ltrim("\u{2003}\u{2003}"),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
{"trailingKept":"été  ","allWhitespace":""}