twig/string-extra
Twig extension integrating Symfony String: add filters u (UnicodeString methods), slug (AsciiSlugger), and singular/plural (Inflector) to manipulate text, generate slugs, and handle basic inflection directly in Twig templates.
laravel-twig) or Blade, where string manipulation in templates is frequent. For Blade, custom directives or helpers bridge the gap without requiring Twig. Poor fit for API-first or backend-only Laravel apps where string ops belong in controllers/services.String component (e.g., UnicodeString, AsciiSlugger, Inflector), which aligns with Laravel’s Str helper but offers Twig-native operations. Reduces redundancy if Symfony String is already used (e.g., for form handling or validation).{{ slugify($title) }}). Requires minimal boilerplate (10–20 lines of PHP).{{ twig_slug($title) }}). Risk of namespace collisions.laravel-twig. Filters like | slug are intuitive for teams familiar with Twig.symfony/string:^5.4. Mitigate with:
"require": {
"symfony/string": "^6.0"
},
"conflict": {
"symfony/string": "6.0.*"
}
symfony/string:^6.0 to ensure compatibility with Laravel’s Str helper.String is stable, but monitor for v7.0 (if released). Twig string-extra has no major changes since v3.24.0 (2026).php artisan view:clear
@once directives or cache compiled views.UnicodeString handles most cases, but test edge cases:
🚀 → ? in slugs).Café → cafe vs. cafe-au-lait).null | slug) crash the view. Use fallbacks:
Blade::directive('safeSlug', function ($expression) {
return "<?php echo {$expression} ?? 'default-slug'; ?>";
});
String conflicts be resolved (e.g., conflict vs. replace in Composer)?{{ items | map(attribute) | slug }})? If yes, offload to PHP.Str:: calls in Blade/templates need replacement? Prioritize high-impact use cases (e.g., SEO slugs).String introduces breaking changes (e.g., custom Str wrapper)?| Stack | Fit | Implementation | Priority |
|---|---|---|---|
| Laravel + Blade | Medium | Custom directives or global helpers | High |
| Laravel + Twig | High | Native StringExtension |
Critical |
| Laravel + Livewire | Low (Server-side only) | Use in Livewire methods (not templates) | Low |
| Laravel + Inertia | Low (Client-side) | Backend logic (e.g., API responses) | Avoid |
| Laravel + API | None | Use Str::of() in controllers |
N/A |
Assessment Phase (1 Week)
Str::slug(), ucfirst(), substr()).grep -r "Str::" resources/views/ | grep -E "slug|ucwords|limit"
Pilot Phase (2 Weeks)
slugify directive for blog slugs.Laravel 10 Features → /laravel-10-features).Str:: calls.STRING_OPERATIONS.md.Rollout Phase (3 Weeks)
{{ Str::slug($post->title) }}{{ slugify($post->title) }} (Blade) or {{ $post->title | slug }} (Twig)./**
* @deprecated Use {{ slugify($var) }} in Blade.
*/
function old_slugify($str) { ... }
php artisan test --filter StringTests).Optimization Phase (Ongoing)
| truncate(100, '...')).String v6.x). Laravel 10/11 compliant.symfony/string:^6.0.symfony/string:^5.4 (but miss v6 features like transliterate()).StringExtension (if using laravel-twig).save()).Dependency Setup
composer require twig/string-extra symfony/string:^6.0
Add to composer.json:
"conflict": {
"symfony/string": "6.0.*"
}
Blade Integration
Register directives in app/Providers/BladeServiceProvider.php:
public function boot() {
Blade::directive('slugify', function ($expression) {
return "<?php echo \\Symfony\\Component\\String\\UnicodeString::from({$expression})->slug(); ?>";
});
Blade::directive('truncate', function ($expression, $args) {
list($length, $ellipsis) = $args ? explode(',', $args, 2) : [100, '...'];
return "<?
How can I help you explore Laravel packages today?