← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Unicode Fundamentals

i18n PHP 5.0+ Intermediate
debt(d5/e3/b7/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list phpstan and phpcs as the tools, and the code_pattern explicitly calls out strlen(), strtolower(), substr() on multibyte text — these are catchable by specialist static analysis tools but not by the compiler or default linting passes.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is a pattern-level swap: replace strlen→mb_strlen, strtolower→mb_strtolower, substr→mb_substr. However, the common_mistakes also include MySQL utf8→utf8mb4 migration and adding mb_internal_encoding(), which pushes slightly beyond a single one-line patch into a small consistent refactor, landing at e3.

b7 Burden Structural debt — long-term weight of choosing wrong

Closest to 'strong gravitational pull' (b7). The term applies_to all contexts (web, cli, queue-worker) across PHP 5.0+. Every developer touching user-supplied text must keep the mb_* discipline in mind; string handling decisions ripple through form inputs, database columns, API responses, and logging. The MySQL utf8 vs utf8mb4 issue further means the schema itself is shaped by this choice.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field states developers conflate UTF-8 and Unicode (the encoding vs. the character set). Beyond that, PHP's byte-based string functions silently return wrong results — strlen('ñ') returning 2 looks correct until it doesn't, MySQL's utf8 charset silently dropping emoji, and Unicode normalisation forms causing invisible inequality. These contradict how developers familiar with ASCII-only or other languages expect strings to work, qualifying as a serious, multi-layered trap.

About DEBT scoring →

Also Known As

UTF-8 code points multibyte Unicode

TL;DR

Unicode assigns every character a code point — UTF-8 encodes these as 1-4 bytes, making it the universal encoding for text on the web.

Explanation

Unicode assigns every character a unique code point (U+0041 = 'A', U+1F600 = 😀). UTF-8 encodes code points as 1-4 bytes: ASCII characters use 1 byte (backwards compatible), Latin extended use 2 bytes, most CJK characters use 3 bytes, emoji use 4 bytes. PHP's string functions operate on bytes, not characters — strlen('😀') returns 4, not 1. Always use mb_* functions for Unicode strings. MySQL's utf8 is not true UTF-8 (only 3-byte sequences); use utf8mb4 for emoji support.

Common Misconception

UTF-8 and Unicode are the same thing — Unicode is the character set (code points); UTF-8 is one encoding of Unicode. UTF-16 and UTF-32 are other encodings of the same Unicode code points.

Why It Matters

PHP's byte-based string functions silently corrupt Unicode text — strlen('ñ') returns 2 not 1, substr('café', 0, 4) returns 'caf' with a broken byte sequence.

Common Mistakes

  • Using strlen() instead of mb_strlen() for character counts.
  • MySQL utf8 charset — only supports 3-byte UTF-8; use utf8mb4 to store emoji and supplementary characters.
  • Not setting mb_internal_encoding('UTF-8') — mb_* functions use a default that may not be UTF-8.
  • Not normalising Unicode before comparison — 'é' can be one code point (U+00E9) or two (e + combining accent); they look identical but are not equal.

Code Examples

✗ Vulnerable
// Byte functions on Unicode — wrong results:
$name = 'José'; // 5 visible chars, 6 UTF-8 bytes ('é' = 2 bytes)
echo strlen($name);         // 6 — byte count, not char count
echo substr($name, 0, 4);   // 'Jos' + broken 'é' byte — corrupted string
echo strtoupper($name);     // 'JOSé' — 'é' not uppercased to 'É'
✓ Fixed
// Multibyte-aware functions:
mb_internal_encoding('UTF-8');
$name = 'José';
echo mb_strlen($name);          // 4 — character count
echo mb_substr($name, 0, 4);    // 'José' — correct
echo mb_strtoupper($name);      // 'JOSÉ' — 'É' correct

// MySQL: utf8mb4 for full Unicode:
CREATE TABLE users (name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci);

Added 15 Mar 2026
Edited 22 Mar 2026
Views 139
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 1 ping S 1 ping S 0 pings M 1 ping T 1 ping W 0 pings T 0 pings F 2 pings S 0 pings S 1 ping M
Bing 1
No pings yesterday
Amazonbot 20 Scrapy 19 Perplexity 10 Google 9 Ahrefs 8 PetalBot 7 SEMrush 6 Bing 5 ChatGPT 4 Unknown AI 4 Brave Search 4 Twitter/X 2 Applebot 2 Meta AI 1 Sogou 1
crawler 98 crawler_json 3 pre-tracking 1
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
UTF-8 i18n UTF-8 is a character encoding that can represent every character in Unicode using 1 to 4 bytes, making it the standard encoding for internationalized text on the web.

UTF-8 is the universal encoding for the modern web—over 98% of websites use it. Getting UTF-8 right from the start prevents corrupted text, broken searches, and frustrated users in any language.

💡 Declare UTF-8 at every layer—file, database, HTTP header, HTML—so there's never a mismatch.

Ask Codex about UTF-8 →
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Always use mbstring functions (mb_strlen, mb_strtolower, mb_substr) instead of their string counterparts when working with user-supplied text that may contain multibyte characters
📦 Applies To
PHP 5.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
strlen() on user-submitted text; strtolower() on international names; substr() truncating multibyte characters creating invalid UTF-8
Auto-detectable: ✓ Yes phpstan phpcs
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update
CWE-116 CWE-838


✓ schema.org compliant