At 2 a.m. on a Thursday, I was staring at a Laravel API response where Arabic text looked like garbage. "اينمك" instead of "أين مكانك?"—a restaurant location query for a client in Abu Dhabi. This wasn't my first time dealing with Arabic integration, but it reminded me why I keep detailed notes. Turns out PHP 8.1's default mbstring settings were fighting with MySQL 8.0's collation in a way I hadn't expected.
Database Configuration Gotchas
Let's get the boring stuff out of the way first: your MySQL database needs to actually want these accented characters. UTF8MB4 support isn't just checking a box—it requires four specific settings:
- •Character set for the connection (
SET NAMES 'utf8mb4') - •Tables created with
COLLATE=utf8mb4_unicode_ci - •Columns individually set to
utf8mb4_unicode_ci - •The database configuration in Laravel's
.envneedingDB_CHARSET=utf8mb4andDB_COLLATION=utf8mb4_unicode_ci
Yes, that means three different layers (connection, table, column) all have to agree. I wasted 4 hours once because a client's migration had forgotten to specify collation on a JSON column—everything looked fine in Postman until someone tested with ة or ل.
Using Raw SQL for Problem Columns
ALTER DATABASE yourDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE yourTable CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;I know Eloquent has tools for this, but sometimes you need brute force when dealing with legacy data from systems that treated Arabic as an afterthought.
Laravel's Hidden Encoder
The framework's JsonResponse class likes to play games. By default, it'll encode your Arabic strings through json_encode, which does UTF-8 handling... unless you're using PHP 8.1's weirdly strict mode. Add these two lines to your AppServiceProvider:
'response' => JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
'DEFAULT_CHARSET' => 'UTF-8'Also check your bootstrap/app.php has ->withFacades()—missing that once made Storage URLs break Arabic file names in a real estate project I did for Dubai properties.
Don't Trust Postman's Preview
You'll swear your API is broken until you realize Postman shows raw UTF-8 bytes sometimes. Always test with actual app code from your React Native client (or whatever front end you're using). The Tawasul Limo team had a week-long argument about Arabic directionality that boiled down to "didn't test on the actual iOS app."
Handling Input from Arab Clients
Arabian business users have specific needs. A logistics company in Sharjah once wanted to handle phone numbers like ٠٥٠٥٥٥٥٥٥ (Arabic numerals) but their sales reps sometimes typed 0505555555. We used Normalizer::normalize() from the symfony/polyfill-intl-normalizer package to standardize inputs:
use Normalizer;
function normalizeArabic($text) {
return Normalizer::normalize($text, Normalizer::FORM_KC);
}This became part of our validation pipeline. For form requests, I often reference Zod Schema Validation: How I Validate API Inputs on Every Project when building the front end too.
Common Validation Needs
- Minimum 3 Arabic chars for business names
- Mobile number pattern matching both Arabic/Persian numbers
- Full-width punctuation cleanup
- Sanitizing zero-width joiners from paste input
Encoding Traps After PHP 8.0 Upgrade
Upgrading from PHP 7.4 to 8.1 bit me on two projects. The php8.1-intl extension became required for proper handling—composer install wouldn't warn you, but suddenly str_contains would silently fail with Arabic text. Don't believe the upgrade guides that say "mbstring covers everything."
Had to manually add:
sudo apt install -y php8.1-intlAnd restart PHP-FPM. This showed up as a missing intl_get_error_code() during some date parsing with Arabic month names. I ended up writing a blog post about PHP 8.1's encoding changes that gets shared more than I'd expected.
Frequently Asked Questions
Why does Laravel still show question marks in Arabic text?
Your database connection isn't using UTF8MB4. Check DB_CHARSET in .env AND the actual MySQL config. I've had clients with MySQL set correctly but Laravel's cache was holding old settings—try php artisan config:clear.
Can I use varchar(255) for Arabic phone numbers?
Yes but be cautious. Arabic numerals take 4 bytes per digit in UTF-8, so same storage as 255 English chars. But a 12-character Arabic number can take same space as 255 letters—something to watch with indexes. We hit this on a UAE banking app and had to optimize index lengths.
How to handle Arabic URL slugs in Laravel?
Use Str::slug($text, '', 'ar') but watch out for invalid characters. Better to store slugs in ASCII but display Arabic in page titles/meta. DAS Holding's Arabic URLs work this way—slug is always Latin for simplicity.
Does Sanctum work with Arabic in tokens?
Yes for token names, but remember to use rawurlencode() when passing Arabic in URLs. We had a refresh token error with Tawasul Limo because a client's app wasn't encoding Arabic spaces properly.
Contact me through sarahprofile.com/contact for custom APIs or book a free consultation here if you're building a bilingual product in Abu Dhabi or Dubai.