Skip to Content
Course content

56: Working with Multibyte Strings

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I want to show you a bug that has bitten almost every PHP developer I've ever mentored. It usually happens when a project grows from a local "English-only" prototype to a real-world application where users might have names like "François" or use emojis in their bios.

<?php
$bio = "I love 🍕 and coding!";
$preview = substr($bio, 0, 10);

echo "Preview: " . $preview;
// Expected: "I love 🍕"
// Actual: "I love "
?>

If you run this, you'll notice that the emoji doesn't render correctly at the end of the string. Instead, you get a weird replacement character (often a diamond with a question mark). You might think your database encoding is wrong or that the browser is acting up, but the problem is actually right here in the PHP code.

The Byte vs. Character Trap

Here is the deal: standard PHP string functions like strlen() and substr() are "byte-oriented." They don't actually know what a "character" is; they only know how many bytes of data are in the string.

In the old days of ASCII, one character always equaled one byte. But we live in a UTF-8 world now. In UTF-8, a standard English letter is 1 byte, but an emoji or a complex character can be anywhere from 2 to 4 bytes. When we told PHP to substr($bio, 0, 10), it counted exactly 10 bytes. Because the pizza emoji starts at byte 8 and ends at byte 11, we sliced the emoji right in the middle. We handed the browser a fragment of a character, and the browser had no choice but to show an error symbol.

Moving to Multibyte Functions

To fix this, you need to stop using the base string functions and start using the mbstring (multibyte string) extension. These functions are designed to understand character encoding, meaning they count characters, not bytes.

<?php
$bio = "I love 🍕 and coding!";
// We use mb_substr instead of substr
$preview = mb_substr($bio, 0, 10, 'UTF-8');

echo "Preview: " . $preview; 
// Result: "I love 🍕"
?>

By switching to mb_substr(), PHP looks at the UTF-8 sequence and says, "Okay, this emoji is one single character, even if it takes up 4 bytes." It handles the math for you so you don't accidentally mutilate your users' data.

Consistency Across Your App

Once you realize you need mb_substr(), you'll realize you probably need a few others too. If you're building a site that supports multiple languages, I strongly suggest you swap out these common functions across your entire codebase:

  • strlen() $\rightarrow$ mb_strlen()
  • strpos() $\rightarrow$ mb_strpos()
  • strtolower() $\rightarrow$ mb_strtolower()
  • substr() $\rightarrow$ mb_substr()

One quick tip: most modern PHP installations have mbstring enabled by default, but if you get a "Call to undefined function" error, you'll need to enable it in your php.ini file or install it via your package manager (e.g., sudo apt-get install php-mbstring). It's a dependency you simply cannot live without in modern web development.




📋 Practical Task

Exercise: Building a Safe International Username Validator

You are building a registration system that requires usernames to be between 3 and 15 characters long. However, you want to support international users who might use non-Latin characters (like "ユーザー" or "Müller").

Write a PHP script that does the following:

  • Creates an array of test usernames containing a mix of English, accented characters, and emojis.
  • Loops through the array and uses mb_strlen() to check if the length is within the 3-15 character range.
  • Prints whether each username is "Valid" or "Invalid".
  • Challenge: Ensure that if a username is too long, you provide a "Suggested" version that is safely truncated to 15 characters using mb_substr() without breaking any multibyte characters.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.