spatie/string
Fluent string handling for PHP. Wrap strings with string() to get a chainable object with helpers like between(), case conversion, concatenation, and array-offset access for reading/updating characters. Lightweight utility by Spatie, installable via Composer.
Install the package via Composer:
composer require spatie/string
First Use Case: Transform and extract text from a user input field (e.g., a blog post title or description).
use Spatie\String\String;
// Basic usage: Wrap a string and chain methods
$title = String::make(' My Awesome Blog Post ')->trim()->toLower()->slugify();
echo $title; // "my-awesome-blog-post"
// Extract content between delimiters
$content = String::make('Hello, world! This is a test.')
->between('Hello, ', 'test.')
->toUpper();
echo $content; // "world!"
Where to Look First:
slugify(), camelCase()).Leverage method chaining for readable, composable text transformations:
// Normalize and truncate a product description
$description = String::make($rawDescription)
->trim()
->replaceFirst('old', 'new')
->tease(100, '...')
->toHtml(); // Escape HTML entities if needed
Pattern: Use in Form Requests, Value Objects, or Service Layer methods to encapsulate logic:
// In a Form Request
public function rules(): array
{
return [
'title' => ['required', 'string', function ($attribute, $value, $fail) {
$slug = String::make($value)->slugify();
if (Post::where('slug', $slug)->exists()) {
$fail('The '.$attribute.' has already been taken.');
}
}]
];
}
Modify specific characters via offset notation:
// Fix typos or format text dynamically
$text = String::make('Hello, W0rld!');
$text[7] = 'r'; // Replace '0' with 'r'
$text[8] = 'l'; // Replace 'r' with 'l'
echo $text; // "Hello, World!"
Use Case: Dynamic form validation or text normalization (e.g., correcting common typos).
Combine Spatie’s methods with Underscore’s utilities (e.g., slugify(), camelCase()):
// Generate a URL-friendly slug from a title
$slug = String::make('User Profile: John Doe')
->slugify()
->prefix('user-')
->toLower();
echo $slug; // "user-user-profile-john-doe"
Pattern: Use in Model Observers, Accessors, or API Resources for consistent text formatting:
// In a Model Accessor
public function getFormattedNameAttribute()
{
return String::make($this->name)
->trim()
->titleize()
->toHtml();
}
between() and segment()Extract substrings for data parsing or validation:
// Parse a filename or path
$filename = String::make('/uploads/images/photo_2023.jpg')
->segment('/', -1) // Last segment: "photo_2023.jpg"
->prefix('media/')
->toString();
echo $filename; // "media/photo_2023.jpg"
// Extract content between tags (e.g., for sanitization)
$cleanText = String::make('<p>Hello</p> <script>alert(1)</script>')
->between('<p>', '</p>')
->toHtml(); // "Hello"
Use Case: File upload handling, HTML sanitization, or log parsing.
Use in Blade templates for localized or context-aware text:
{{ String::make($user->name)
->possessive()
->toHtml()
->prefix('Account of ')
}}
Output: "Account of John's"
PHP 8+ Requirement (v3.0.0+)
php: in composer.json or use spatie/string:^2.2 for PHP 7 support.Non-String Inputs Throw Exceptions
__toString() will throw:
String::make([]); // Throws \Spatie\String\Exceptions\InvalidStringException
(string) cast or toString():
String::make((string) $nonStringObject);
Underscore Methods May Not Chain
isEmail() return booleans and break chaining:
String::make('test@example.com')->isEmail()->toUpper(); // Error!
$isValid = String::make($email)->isEmail();
if ($isValid) { ... }
possessive() Edge Cases
"it" (returns "it's" instead of "its").if (String::make($word)->isNotEmpty() && $word !== 'it') {
$possessive = String::make($word)->possessive();
}
Offset Assignment Overwrites Entire String
String::make('abc')->offsetSet(5, 'x'); // Returns "x"
substr() manually.Inspect Intermediate Steps
Use toString() to debug chains:
$step1 = String::make(' test ')->trim()->toString(); // "test"
$step2 = $step1->toUpper()->toString(); // "TEST"
Leverage dd() for Complex Chains
Break down long chains in Tinker or debuggers:
dd(
String::make($input)
->replaceFirst('old', 'new')
->segment('/', 1)
->toString()
);
Test Edge Cases
segment() with \n).String::make('')->between('a', 'b'); // Returns empty string
String::make('café')->slugify(); // "cafe" (handles accents)
Create Custom Methods
Extend the String class to add domain-specific logic:
// app/Extensions/StringExtensions.php
namespace App\Extensions;
use Spatie\String\String;
class StringExtensions
{
public static function initialize()
{
String::macro('toTitleCase', function () {
return str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $this->toString())));
});
}
}
Register in AppServiceProvider:
public function boot()
{
\App\Extensions\StringExtensions::initialize();
}
Usage:
String::make('hello_world')->toTitleCase(); // "HelloWorld"
Override Underscore Methods
Replace or extend Underscore’s methods (e.g., customize slugify()):
String::macro('customSlugify', function () {
return $this->slugify()->replace(['-', '_'], '-');
});
Integrate with Laravel’s Helpers
Add a global helper in composer.json:
"extra": {
"laravel": {
"providers": ["Spatie\\String\\StringServiceProvider"]
}
}
Now use string() globally:
string('test')->toUpper(); // "TEST"
String instance. For heavy operations (e.g., bulk processing), minimize chains:
// Less efficient
foreach ($items as $item) {
String::make($item)->slugify()->to
How can I help you explore Laravel packages today?