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 Grapheme Laravel Package

symfony/polyfill-intl-grapheme

Native PHP polyfill for the Intl Grapheme functions, for working with UTF-8 grapheme clusters. Provides grapheme_strlen, grapheme_substr, grapheme_strpos/stripos, grapheme_extract, grapheme_str_split, and related helpers when ext-intl isn’t available.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation (unchanged):

    composer require symfony/polyfill-intl-grapheme:^1.38
    

    Ensure your project targets PHP 8.6+ for native grapheme_strrev() support.

  2. First Use Case (unchanged): Reverse strings with grapheme awareness (e.g., RTL languages, emojis):

    use function Symfony\Polyfill\Intl\Grapheme\grapheme_strrev;
    
    $reversed = grapheme_strrev("مدم"); // Arabic palindrome → "مدم" (correct)
    $emojiReversed = grapheme_strrev("👨‍👩‍👧‍👦"); // Emoji cluster preserved
    
  3. Laravel Integration (unchanged): Add a Str helper macro for consistency:

    // app/Helpers/StrHelper.php
    use Illuminate\Support\Str;
    use function Symfony\Polyfill\Intl\Grapheme\grapheme_strrev;
    
    Str::macro('graphemeReverse', fn($string) => grapheme_strrev($string));
    

Implementation Patterns

Core Workflows (updated)

  1. RTL Language Support (unchanged):

    • Reverse text for mirrored UI elements (e.g., search suggestions, autocomplete):
      $rtlInput = "مرحبا"; // "Hello" in Arabic
      $reversed = Str::graphemeReverse($rtlInput); // "ابحرم"
      
  2. Emoji/Combining Character Handling (unchanged):

    • Preserve clusters in emojis or accented text:
      $familyEmoji = "👨‍👩‍👧‍👦";
      $reversed = Str::graphemeReverse($familyEmoji); // Cluster intact
      
  3. Grapheme Splitting (new focus):

    • Fix for PCRE 8 compatibility: Use grapheme_str_split() for reliable grapheme boundaries:
      $text = "éléphant";
      $clusters = grapheme_str_split($text);
      // Now works correctly with PCRE 8 (fixed in v1.38.1)
      
  4. Palindrome Validation (unchanged):

    • Check for grapheme-aware palindromes (e.g., usernames):
      $isPalindrome = Str::graphemeReverse($input) === $input;
      

Laravel-Specific Patterns (unchanged)

  1. Form Request Validation:

    Rule::macro('graphemePalindrome', function () {
        return function ($attribute, $value, $fail) {
            if (Str::graphemeReverse($value) !== $value) {
                $fail('The :attribute must be a grapheme palindrome.');
            }
        };
    });
    
  2. Blade Directives:

    Blade::directive('reverseGraphemes', function ($expression) {
        return "<?php echo Str::graphemeReverse({$expression}); ?>";
    });
    
  3. Stringable Trait Extension:

    Stringable::macro('reverseGraphemes', function () {
        return Str::graphemeReverse($this->value);
    });
    
  4. Search Indexing: Use grapheme_str_split() for preprocessing RTL tokens:

    $tokens = grapheme_str_split($rtlText); // Now reliable with PCRE 8
    $reversedTokens = array_map('grapheme_strrev', $tokens);
    

Gotchas and Tips

Pitfalls (updated)

  1. PHP 8.6 Requirement (unchanged):

    • grapheme_strrev() is native to PHP 8.6+. Earlier versions require a fallback.
  2. PCRE 8 Compatibility (new):

    • grapheme_str_split() now works correctly with PCRE 8 (fixed in v1.38.1).
    • Test with:
      $text = "éléphant";
      $clusters = grapheme_str_split($text);
      // Should split into ["é", "l", "é", "p", "h", "a", "n", "t"] (not broken clusters)
      
  3. Emoji Cluster Edge Cases (unchanged):

    • Some emoji sequences may still behave unexpectedly. Verify clusters with:
      $emoji = "👨‍👩‍👧‍👦";
      $clusters = grapheme_str_split($emoji);
      // Ensure no artificial splits between skin tone and base emoji
      
  4. Performance in Loops (unchanged):

    • grapheme_strrev() is slower than strrev() for ASCII text. Cache results or use strrev for ASCII-only paths.
  5. Combining Character Order (unchanged):

    • Reversing strings with combining marks (e.g., "éléphant") may still require validation.

Debugging Tips (updated)

  1. Verify Grapheme Clusters (updated): Use grapheme_str_split() to inspect clusters (now reliable with PCRE 8):

    $clusters = grapheme_str_split("مدم");
    print_r($clusters); // ["م", "د", "م"] (correct)
    
  2. Compare with intl Extension (unchanged): Cross-validate results if intl is available:

    $polyfillResult = grapheme_strrev($text);
    $intlResult = IntlGraphemeClusterIterator::reverse($text);
    assert($polyfillResult === $intlResult, "Results mismatch!");
    
  3. Check PHP/PCRE Version: Ensure compatibility:

    php -r "echo PHP_VERSION_ID >= 80600 ? 'PHP 8.6+' : 'Upgrade PHP';"
    php -r "echo preg_version() >= '10.42' ? 'PCRE 10.42+' : 'Check PCRE compatibility';"
    

Extension Points (updated)

  1. Custom Fallback Logic (unchanged): Extend for unsupported PHP versions:

    function grapheme_strrev($string) {
        if (PHP_VERSION_ID >= 80600) {
            return \grapheme_strrev($string);
        }
        return \Symfony\Component\Polyfill\Intl\Grapheme\StringHelper::strrev($string);
    }
    
  2. Laravel Service Provider (unchanged): Register globally for all requests:

    Blade::composer('*', function ($view) {
        if (PHP_VERSION_ID < 80600) {
            $view->share('grapheme_strrev_fallback', true);
        }
    });
    
  3. Testing RTL Scenarios (updated): Add test cases for PCRE 8 compatibility:

    // tests/Feature/GraphemeSplitTest.php
    public function test_pcre8_compatibility()
    {
        $text = "éléphant";
        $clusters = grapheme_str_split($text);
        $this->assertCount(8, $clusters);
    }
    
  4. New: Grapheme-Aware String Manipulation: Leverage grapheme_str_split() for advanced use cases:

    // Example: Reverse words in RTL text while preserving graphemes
    $rtlText = "مرحبا بالعالم";
    $words = grapheme_str_split($rtlText);
    $reversedWords = array_reverse($words);
    $reversedText = implode('', $reversedWords); // "العالم مرحبا"
    
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.
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
anil/file-picker
broqit/fields-ai