symfony/polyfill-mbstring
Native PHP polyfill for the mbstring extension, providing partial mb_* functionality when the mbstring extension isn’t available. Part of Symfony’s Polyfill suite for consistent multibyte string handling across environments.
Installation: Update to the latest version of the polyfill:
composer require symfony/polyfill-mbstring:^1.38
Ensure ext-iconv is enabled (required for the polyfill to function):
docker-php-ext-install iconv # For Docker environments
First Use Case:
Use mb_* functions in your Laravel application without worrying about ext-mbstring availability. The polyfill now handles edge cases better, including:
use Symfony\Polyfill\Mbstring\Mbstring;
// Handle null inputs (new in v1.38)
$length = mb_strlen(null); // Returns 0 (previously might throw error)
// Process invalid UTF-8 input (fixed in v1.38)
$length = mb_strlen("\xFF\xFE\xFD"); // Returns 3 (previously might fail)
Laravel-Specific Setup:
mb_strlen in custom rules (now safer with null inputs):
use Illuminate\Validation\Rule;
'username' => [
'required',
Rule::unique('users')->whereNull('deleted_at'),
function ($attribute, $value) {
return $value === null ? false : mb_strlen($value) <= 50;
},
],
Verify Functionality: Test with multibyte strings, null inputs, and invalid UTF-8:
dd(
mb_strlen("こんにちは"), // 5
mb_strlen(null), // 0 (new behavior)
mb_strlen("\xFF\xFE\xFD"), // 3 (fixed)
mb_convert_encoding("&", 'HTML-ENTITIES') // Matches native output (fixed)
);
Unicode-Aware String Operations (Updated):
Replace native string functions with mb_* equivalents, now with improved handling of edge cases:
// Safe handling of null and invalid UTF-8
$length = mb_strlen($userInput ?? null); // Returns 0 if null
$substring = mb_substr($text, 0, 100, 'UTF-8'); // Explicit encoding (recommended)
Form and Input Validation (Updated):
Use mb_* functions in Laravel validation rules with null checks:
$request->validate([
'title' => 'required|max:100',
'bio' => [
'nullable',
function ($attribute, $value, $fail) {
if ($value !== null && mb_strlen($value) > 500) {
$fail('The bio may not be greater than 500 characters.');
}
},
],
]);
HTML Entity Conversion (Fixed):
Use mb_convert_encoding for consistent HTML entity conversion:
$encoded = mb_convert_encoding("& < >", 'HTML-ENTITIES', 'UTF-8');
// Returns "& < >" (matches native PHP behavior)
Database and ORM (Updated): Handle multibyte strings in Eloquent with null safety:
// Model
public function setSlugAttribute($value) {
$this->attributes['slug'] = $value === null
? null
: mb_strtolower(mb_substr($value, 0, 50, 'UTF-8'));
}
API Responses (Updated): Ensure API responses handle multibyte strings and edge cases:
return response()->json([
'message' => mb_substr($longText ?? '', 0, 100, 'UTF-8'),
'truncated' => $longText !== null && mb_strlen($longText) > 100,
]);
Feature Development (Updated):
mb_* functions for clarity and consistency:
public function translate(TranslateRequest $request) {
$text = $request->text ?? '';
$translated = $this->translationService->translate($text);
return response()->json([
'original' => mb_substr($text, 0, 100, 'UTF-8'),
'translated' => mb_substr($translated ?? '', 0, 100, 'UTF-8'),
]);
}
Legacy Code Migration (Updated):
strlen, substr, and strpos with mb_* equivalents, adding null checks:
// Before:
$length = strlen($userInput);
// After:
$length = $userInput === null ? 0 : mb_strlen($userInput, 'UTF-8');
Testing (Updated):
public function testMbStringEdgeCases() {
$this->assertEquals(0, mb_strlen(null));
$this->assertEquals(3, mb_strlen("\xFF\xFE\xFD"));
$this->assertEquals("&", mb_convert_encoding("&", 'HTML-ENTITIES'));
}
CI/CD Integration (Updated):
# .github/workflows/tests.yml
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
php: ['7.4', '8.0', '8.1', '8.2']
steps:
- uses: actions/checkout@v3
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: iconv
- run: composer install
- run: composer test -- --filter="testMbStringEdgeCases"
Laravel Validation (Updated): Create a reusable validation rule for multibyte strings with null safety:
class MbStringLength extends Rule {
protected $max;
public function __construct($max) {
$this->max = $max;
}
public function passes($attribute, $value) {
return $value === null || mb_strlen($value, 'UTF-8') <= $this->max;
}
}
Middleware for UTF-8 Enforcement (Updated): Ensure UTF-8 encoding and handle edge cases:
namespace App\Http\Middleware;
use Closure;
class EnforceUtf8 {
public function handle($request, Closure $next) {
mb_internal_encoding('UTF-8');
mb_regex_encoding('UTF-8');
return $next($request);
}
}
Service Providers (Updated): Bootstrap multibyte settings with explicit encoding:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider {
public function boot() {
mb_internal_encoding('UTF-8');
mb_regex_encoding('UTF-8');
}
}
Artisan Commands (Updated): Handle multibyte strings and null inputs in CLI:
namespace App\Console\Commands;
use Illuminate\Console\Command;
class TruncateCommand extends Command {
protected $signature = 'app:truncate {text?} {limit}';
protected $description = 'Truncate multibyte text';
public function handle() {
$text = $this->argument('text') ?? '';
$truncated = mb_substr($text, 0, $this->argument('limit'), 'UTF-8');
$this->info($truncated);
}
}
Queue Jobs (Updated): Handle multibyte strings and null values in jobs:
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class ProcessText implements ShouldQueue {
use Queueable;
protected $text;
public function __construct($text = null) {
$this->text = $text;
}
public function handle() {
$length = $this->text === null ? 0 : mb_strlen($this->text, 'UTF-8');
// Process text...
}
}
Null Input Handling:
mb_strlen(null) might throw a warning or error.0 (safe), but always explicitly check for null in business logic.Invalid UTF-8 Input:
How can I help you explore Laravel packages today?