symfony/polyfill-intl-normalizer
Fallback implementation of PHP Intl’s Normalizer class when the intl extension isn’t available. Part of Symfony’s Polyfill suite, providing compatible Unicode normalization support across environments under the MIT license.
## Getting Started
### Minimal Steps
1. **Installation**:
Update the package via Composer (or install if new):
```bash
composer require symfony/polyfill-intl-normalizer:^1.38
No additional configuration is required—Laravel’s autoloader handles the rest.
First Use Case:
Use the new normalizer_get_raw_decomposition() functionality for advanced Unicode decomposition:
use Symfony\Component\Polyfill\Intl\Normalizer;
$decomposition = Normalizer::getRawDecomposition('é'); // Returns ['e', '´']
Validation:
Test in environments where the intl extension is disabled (e.g., Docker with intl removed):
RUN docker-php-ext-disable intl
Verify the new method works as expected without errors.
Raw Unicode Decomposition:
Use getRawDecomposition() to inspect how characters break down (e.g., for custom normalization logic):
$rawDecomposition = Normalizer::getRawDecomposition('café');
// Returns: ['c', 'a', 'f', 'e', '´']
Custom Normalization Logic:
Combine getRawDecomposition() with Laravel’s Str for advanced slug generation:
$rawParts = Normalizer::getRawDecomposition($string);
$slug = Str::slug(implode('', $rawParts));
Debugging Unicode Issues: Inspect decomposed parts to debug unexpected normalization behavior:
$decomposed = Normalizer::getRawDecomposition($userInput);
dd($decomposed); // Log or inspect in Laravel Telescope
Laravel-Specific Integrations:
public function getNormalizedNameAttribute()
{
$raw = Normalizer::getRawDecomposition($this->attributes['name']);
return implode('', $raw);
}
$decomposed = Normalizer::getRawDecomposition($request->input);
if (in_array(' ', $decomposed, true)) {
$this->errors()->add('input', 'Spaces not allowed in decomposed form.');
}
Performance-Conscious Usage: Cache raw decompositions for repeated operations (e.g., search indexing):
$cacheKey = 'decomposed_'.$string;
$decomposed = Cache::remember($cacheKey, now()->addHours(1), function() use ($string) {
return Normalizer::getRawDecomposition($string);
});
Feature Development:
getRawDecomposition() during local development to prototype custom normalization rules.$testChars = ['é', 'ß', '😊', 'Z̃'];
foreach ($testChars as $char) {
dd(Normalizer::getRawDecomposition($char));
}
Migration from Native intl:
Normalizer::getRawDecomposition() calls with the polyfill’s equivalent:
// Native intl (if available)
$nativeDecomp = Normalizer::getRawDecomposition($string);
// Polyfill fallback
$polyfillDecomp = \Symfony\Component\Polyfill\Intl\Normalizer::getRawDecomposition($string);
Performance Optimization:
getRawDecomposition() against native intl for critical paths:
composer require --dev symfony/var-dumper
vendor/bin/blackfire run php artisan tinker --execute='\Symfony\Component\Polyfill\Intl\Normalizer::getRawDecomposition("café");'
composer.json for stability:
"symfony/polyfill-intl-normalizer": "^1.38"
mbstring is loaded (required for the polyfill):
if (!extension_loaded('mbstring')) {
throw new RuntimeException('mbstring extension is required for the Normalizer polyfill.');
}
getRawDecomposition() in PHPUnit to simulate environments without intl:
$this->partialMock(Normalizer::class, ['getRawDecomposition'])
->expects($this->any())
->method('getRawDecomposition')
->willReturn(['c', 'a', 'f', 'e', '´']);
Performance Overhead:
getRawDecomposition() is slower than native intl (5–20x for large datasets).Edge-Case Unicode Handling:
$edgeCases = ['\u{D800}\u{DC00}', '\u{00A0}', '\u{1F600}'];
foreach ($edgeCases as $char) {
dd(Normalizer::getRawDecomposition($char));
}
mbstring Dependency:
mbstring is disabled. Always validate:
if (!extension_loaded('mbstring')) {
throw new RuntimeException('mbstring extension required for Normalizer polyfill.');
}
Laravel-Specific Quirks:
$model->setAttribute('name', implode('', Normalizer::getRawDecomposition($model->name)));
@php directives to avoid rendering issues:
@php
$decomposed = Normalizer::getRawDecomposition($variable);
@endphp
{{ implode('', $decomposed)}}
CI/CD Testing:
intl disabled to catch polyfill-specific issues:
jobs:
test:
strategy:
matrix:
php-ext-intl: [enabled, disabled]
steps:
- run: docker-php-ext-${{ matrix.php-ext-intl }} intl
- run: composer test
Class/Method Not Found:
composer update symfony/polyfill-intl-normalizer --with-all-dependencies
dd(method_exists(Normalizer::class, 'getRawDecomposition')); // Should return true
Unexpected Decomposition Results:
intl (if available):
$nativeDecomp = Normalizer::getRawDecomposition($string); // Native intl
$polyfillDecomp = \Symfony\Component\Polyfill\Intl\Normalizer::getRawDecomposition($string);
dd($nativeDecomp === $polyfillDecomp);
Memory Issues:
$batchSize = 100;
foreach (array_chunk(str_split($longString), $batchSize) as $chunk) {
Normalizer::getRawDecomposition(implode('', $chunk));
}
Leverage Laravel Helpers:
Combine getRawDecomposition() with Str for advanced slugs:
$raw = Normalizer::getRawDecomposition($title);
$slug = Str::slug(implode('', $raw));
Normalization Forms:
FORM_C/FORM_D for standard normalization, getRawDecomposition() for custom logic.FORM_KC/FORM_KD unless compatibility is critical.Caching Strategies:
$decomposed = Cache::remember("decomposed_{$string}", now()->addHours(1), function() use ($string) {
return Normalizer::getRawDecomposition($string);
});
Environment-Specific Config:
$decomposed = extension_loaded('intl')
? Normalizer::getRawDecomposition($string)
: \
How can I help you explore Laravel packages today?