Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Polyfill Intl Normalizer Laravel Package

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.

View on GitHub
Deep Wiki
Context7
## 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.

  1. 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', '´']
    
  2. 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.


Implementation Patterns

Usage Patterns

  1. 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', '´']
    
  2. Custom Normalization Logic: Combine getRawDecomposition() with Laravel’s Str for advanced slug generation:

    $rawParts = Normalizer::getRawDecomposition($string);
    $slug = Str::slug(implode('', $rawParts));
    
  3. Debugging Unicode Issues: Inspect decomposed parts to debug unexpected normalization behavior:

    $decomposed = Normalizer::getRawDecomposition($userInput);
    dd($decomposed); // Log or inspect in Laravel Telescope
    
  4. Laravel-Specific Integrations:

    • Eloquent Accessors: Use raw decomposition for custom attribute transformations:
      public function getNormalizedNameAttribute()
      {
          $raw = Normalizer::getRawDecomposition($this->attributes['name']);
          return implode('', $raw);
      }
      
    • Form Requests: Validate decomposed parts for strict input rules:
      $decomposed = Normalizer::getRawDecomposition($request->input);
      if (in_array(' ', $decomposed, true)) {
          $this->errors()->add('input', 'Spaces not allowed in decomposed form.');
      }
      
  5. 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);
    });
    

Workflows

  1. Feature Development:

    • Use getRawDecomposition() during local development to prototype custom normalization rules.
    • Test edge cases (e.g., surrogate pairs, combining characters) with:
      $testChars = ['é', 'ß', '😊', 'Z̃'];
      foreach ($testChars as $char) {
          dd(Normalizer::getRawDecomposition($char));
      }
      
  2. Migration from Native intl:

    • Replace 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);
      
    • Use feature flags to toggle between implementations during testing.
  3. Performance Optimization:

    • Benchmark 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é");'
      
    • Avoid calling it in loops unless necessary (e.g., batch process with chunking).

Integration Tips

  • Dependency Management: Pin the version in composer.json for stability:
    "symfony/polyfill-intl-normalizer": "^1.38"
    
  • Runtime Checks: Ensure mbstring is loaded (required for the polyfill):
    if (!extension_loaded('mbstring')) {
        throw new RuntimeException('mbstring extension is required for the Normalizer polyfill.');
    }
    
  • Testing: Mock getRawDecomposition() in PHPUnit to simulate environments without intl:
    $this->partialMock(Normalizer::class, ['getRawDecomposition'])
         ->expects($this->any())
         ->method('getRawDecomposition')
         ->willReturn(['c', 'a', 'f', 'e', '´']);
    

Gotchas and Tips

Pitfalls

  1. Performance Overhead:

    • getRawDecomposition() is slower than native intl (5–20x for large datasets).
    • Mitigation: Cache results aggressively or avoid in high-throughput loops.
  2. Edge-Case Unicode Handling:

    • Rare characters (e.g., surrogate pairs, legacy encodings) may return unexpected arrays.
    • Mitigation: Test with your project’s dataset:
      $edgeCases = ['\u{D800}\u{DC00}', '\u{00A0}', '\u{1F600}'];
      foreach ($edgeCases as $char) {
          dd(Normalizer::getRawDecomposition($char));
      }
      
  3. mbstring Dependency:

    • The polyfill fails silently if mbstring is disabled. Always validate:
      if (!extension_loaded('mbstring')) {
          throw new RuntimeException('mbstring extension required for Normalizer polyfill.');
      }
      
  4. Laravel-Specific Quirks:

    • Eloquent: Raw decomposition may not persist correctly if attributes are cast/mutated. Normalize before saving:
      $model->setAttribute('name', implode('', Normalizer::getRawDecomposition($model->name)));
      
    • Blade: Use @php directives to avoid rendering issues:
      @php
          $decomposed = Normalizer::getRawDecomposition($variable);
      @endphp
      {{ implode('', $decomposed)}}
      
  5. CI/CD Testing:

    • Test with 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
      

Debugging

  1. Class/Method Not Found:

    • Ensure the updated package is installed:
      composer update symfony/polyfill-intl-normalizer --with-all-dependencies
      
    • Verify the method exists:
      dd(method_exists(Normalizer::class, 'getRawDecomposition')); // Should return true
      
  2. Unexpected Decomposition Results:

    • Compare output with native intl (if available):
      $nativeDecomp = Normalizer::getRawDecomposition($string); // Native intl
      $polyfillDecomp = \Symfony\Component\Polyfill\Intl\Normalizer::getRawDecomposition($string);
      dd($nativeDecomp === $polyfillDecomp);
      
  3. Memory Issues:

    • Large decompositions (e.g., long strings) may exhaust memory. Use chunking:
      $batchSize = 100;
      foreach (array_chunk(str_split($longString), $batchSize) as $chunk) {
          Normalizer::getRawDecomposition(implode('', $chunk));
      }
      

Tips

  1. Leverage Laravel Helpers: Combine getRawDecomposition() with Str for advanced slugs:

    $raw = Normalizer::getRawDecomposition($title);
    $slug = Str::slug(implode('', $raw));
    
  2. Normalization Forms:

    • Use FORM_C/FORM_D for standard normalization, getRawDecomposition() for custom logic.
    • Avoid FORM_KC/FORM_KD unless compatibility is critical.
  3. Caching Strategies:

    • Cache decomposed arrays for repeated access:
      $decomposed = Cache::remember("decomposed_{$string}", now()->addHours(1), function() use ($string) {
          return Normalizer::getRawDecomposition($string);
      });
      
  4. Environment-Specific Config:

    • Toggle polyfill usage in production:
      $decomposed = extension_loaded('intl')
          ? Normalizer::getRawDecomposition($string)
          : \
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope