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

At some point in your first few weeks of PHP, you're going to need to trim a long string down—maybe for a blog post preview or a user's "about me" snippet on a profile page. It seems trivial. You just want the first 100 characters, right? If you're thinking substr($text, 0, 100), you're thinking exactly how I did five years ago. It feels efficient, it's a single line of code, and in 90% of your local tests, it works perfectly.

The "Just Cut It" Approach

The naive way to handle string truncation is to treat the string as a simple array of bytes. You tell PHP where to start, how many units to grab, and you're done. It looks like this:

$teaser = substr($blogPostContent, 0, 100) . '...';

This works fine if your content is strictly English ASCII text. But the moment you move this into a production environment where real people provide the data, this approach starts to leak. I've seen this cause "ghost characters" (those weird black diamonds with question marks) to appear at the end of strings in a live app. It's a frustrating bug because it only happens occasionally, usually when a user includes an emoji or a character from a non-Latin alphabet.

Why Bytes Aren't Characters

The problem is that substr() doesn't actually count characters; it counts bytes. In UTF-8 encoding, a standard English letter is one byte, but an emoji or a Cyrillic character can be three or four bytes. If your 100th byte happens to fall in the middle of a multi-byte character, substr() will slice that character right down the middle. You've just created an invalid byte sequence, and the browser has no idea how to render it.

To fix this, you need the mb_ prefix functions. The "mb" stands for multibyte. These functions are aware of the encoding and treat a multi-byte character as a single unit. I always recommend using mb_substr() by default for any user-facing text. It's a tiny bit slower, but the trade-off for not breaking your UI with corrupted characters is a no-brainer.

$teaser = mb_substr($blogPostContent, 0, 100, 'UTF-8') . '...';

The "Half-Word" Problem

Even with mb_substr(), you still have a UX problem: the "half-word" slice. If your 100th character is the letter 'a' in the word 'apple', your teaser ends up looking like: "Check out this amazing recipe for a baked ap...". It looks amateur. To solve this, we have to move beyond a single function and actually reason through the string's structure.

The better way is to truncate the string, and then use mb_strrpos() (which finds the position of the last occurrence of a character) to find the nearest space. By slicing again at that space, you ensure you always end on a complete word. I usually wrap this in a helper function so I don't have to write the logic every time.

function createTeaser($text, $limit = 100) {
    if (mb_strlen($text) <= $limit) {
        return $text;
    }

    // 1. Initial cut
    $text = mb_substr($text, 0, $limit);
    
    // 2. Find the last space to avoid cutting a word in half
    $lastSpace = mb_strrpos($text, ' ');
    
    if ($lastSpace !== false) {
        $text = mb_substr($text, 0, $lastSpace);
    }

    return $text . '...';
}

Now, we've traded a one-liner for a few lines of logic. Is it more complex? Yes. But it's robust. It handles international characters and it respects the readability of the language. As a rule of thumb: whenever you're manipulating strings that come from a user, assume they aren't plain ASCII and assume you'll probably cut a word in half unless you explicitly prevent it.




📋 Practical Task

Building a Robust User-Handle Formatter

You've been asked to create a function that cleans up raw user input to create a "clean" social media handle. The handle must be lowercase, have no trailing or leading whitespace, and cannot be longer than 15 characters. If the handle is truncated, it must not end in a hyphen or underscore (these should be trimmed off if they end up at the end of the string after truncation).

Requirements:

  • Use trim() to handle surrounding whitespace.
  • Use mb_strtolower() for case normalization.
  • Use mb_substr() to enforce the 15-character limit.
  • Use rtrim() to remove any trailing underscores (_) or hyphens (-) that remain after the truncation.

Test your function with this input: " Super_Cool_Developer_2024 ".
Expected Output: "super_cool_dev" (or similar, depending on where the 15-char cut falls and the subsequent rtrim).

Rating
0 0

There are no comments for now.

to be the first to leave a comment.