voku/stringy
voku/stringy is a PHP string manipulation library with a fluent, chainable API and multibyte/Unicode-safe helpers. It offers common text utilities like trimming, casing, slugging, replacing, and comparisons, aiming for predictable results across encodings.
Installation
composer require voku/stringy
Add to composer.json if not using autoloading:
"autoload": {
"psr-4": {
"App\\": "app/",
"Voku\\": "vendor/voku/"
}
}
Run composer dump-autoload.
First Use Case Basic string manipulation:
use Voku\Stringy\Stringy;
$string = new Stringy('Hello, World!');
echo $string->toLower(); // "hello, world!"
Where to Look First
vendor/voku/stringy/src/ for core classes.tests/ for usage examples and edge cases.Chaining Methods Leverage fluent interface for readability:
$result = (new Stringy(' PHP '))
->trim()
->toLower()
->replace('php', 'Laravel')
->__toString();
// "laravel"
Multibyte Support Handle Unicode gracefully:
$string = new Stringy('Café');
echo $string->length(); // 4 (not 5, as 'é' is a single character)
Integration with Laravel
Stringy as a singleton:
$this->app->singleton(Stringy::class, function () {
return new Stringy('');
});
app/Helpers/StringHelper.php:
if (!function_exists('str')) {
function str(string $value) {
return new Stringy($value);
}
}
Use in Blade:
{{ str($user->name)->title()->__toString() }}
Batch Processing Process arrays of strings efficiently:
$strings = ['Hello', 'WORLD', 'Laravel'];
$processed = array_map(fn($s) => (new Stringy($s))->toLower(), $strings);
Validation Integration
Combine with Laravel's Validator:
$validator = Validator::make(['input' => ' test '], [
'input' => ['required', function ($attribute, $value, $fail) {
if ((new Stringy($value))->trim()->isEmpty()) {
$fail('The field is required.');
}
}]
]);
Immutable Operations
Methods like toLower() return a new Stringy instance. Use __toString() or get() to retrieve the modified value:
$string = (new Stringy('HELLO'))->toLower();
echo $string; // "HELLO" (unchanged)
echo $string->__toString(); // "hello"
Performance with Large Strings Avoid chaining heavy operations (e.g., regex) on massive strings. Prefer:
$string = new Stringy($largeString);
$string->replacePattern('/regex/', 'replacement'); // Single operation
Locale-Sensitive Methods
Methods like toTitleCase() may behave unexpectedly without locale settings. Set explicitly:
setlocale(LC_ALL, 'en_US.UTF-8');
$string = (new Stringy('hello world'))->toTitleCase();
// "Hello World"
Edge Cases in split()
Empty delimiters or strings may return unexpected results:
$string = new Stringy('a,b,c');
$string->split(','); // ['a', 'b', 'c']
$string->split(''); // ['a', ',', 'b', ',', 'c'] (not ['a,b,c'])
Inspect Internals
Use get() to debug the current state:
$string = new Stringy('test');
$string->toUpper();
dump($string->get()); // "TEST"
Check for Multibyte Issues Verify encoding with:
$string = new Stringy('Café');
dump(mb_strlen($string->get(), 'UTF-8')); // 4
Override Default Behavior
Extend Stringy for custom logic:
class CustomStringy extends Stringy {
public function customMethod() {
return $this->replace('foo', 'bar')->toUpper();
}
}
Custom Methods Add static methods to a helper class:
class StringHelper {
public static function slugify(string $string): string {
return (new Stringy($string))
->toLower()
->replacePattern('/[^a-z0-9]+/', '-')
->trim('-')
->__toString();
}
}
Laravel Macros
Extend Stringy globally in a service provider:
Stringy::macro('truncate', function ($length) {
return $this->length() > $length
? $this->substr(0, $length).'...'
: $this;
});
Usage:
$string = new Stringy('Laravel is awesome');
echo $string->truncate(10)->__toString(); // "Laravel..."
Performance Optimization Cache repeated operations:
$string = new Stringy('complex string');
$cached = $string->replacePattern('/pattern/', 'replacement');
// Reuse $cached instead of re-running the operation
How can I help you explore Laravel packages today?