str
Create a fluent Stringable from a string, or a proxy to the static Str methods.
str(string|null $string = null): \Illuminate\Support\Stringable|object- Added in Laravel 9.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$stringoptional | string|null= null | The string to wrap. Omitting the argument entirely returns the static-forwarding proxy; explicitly passing null returns a Stringable wrapping an empty string. |
Return value
\Illuminate\Support\Stringable|objectA Stringable wrapping the given string. Called with no arguments at all, it returns a proxy object that forwards method calls to the static Str class.
str() is the shorthand for Str::of(). It returns an Illuminate\Support\Stringable, which wraps the value and exposes every Str method as a chainable instance method — trim, slug, camel, replace, before, after, limit, mask, whenContains and the rest.
Why chain instead of nest
The usual alternative is a stack of nested calls read inside-out: Str::slug(Str::lower(trim($x))). The Stringable version reads left to right in execution order, which is the whole point.
Getting a string back out
A Stringable is an object, not a string. It has __toString(), so echo, interpolation and loose == comparison all work — but a strict === against a string is false, and a string parameter type will only accept it because of coercion. Call ->toString() or cast with (string) when you need a real string, and note that methods like contains() and isEmpty() already return booleans, not Stringables.
The no-argument form
str() with no arguments gives you an object whose method calls forward to the static Str class, so str()->snake('FooBar') works. It is a convenience for avoiding the use statement, not a different API.
Example
When to use it
- Build a URL slug from raw user input in one left-to-right chain.
- Extract and reformat part of a string, such as the local part of an email address.
- Apply a conditional transformation with whenContains or when without breaking the chain.
Frequently asked questions
What is the difference between str() and Str::of()?
Nothing functionally — str('x') is Str::of('x'). The helper is global so it needs no use statement, which matters most in Blade templates and short scripts.
How do I turn a Stringable back into a plain string?
Call ->toString(), cast with (string), or just echo it — Stringable implements __toString(). You need an explicit conversion before a strict === comparison, an in_array with strict mode, or json_encode of the object itself.
What does str() return when called with no arguments?
An anonymous proxy object whose method calls forward to the static Illuminate\Support\Str class, so str()->snake('FooBar') works. It is not an instance of Str, so do not test it with instanceof.
More examples
Chaining beats nesting
Both produce the same string; the chained form states the steps in the order they happen. toString() is called explicitly so the strict === comparison against the nested result succeeds.
<?php
$title = ' The Quick Brown Fox! ';
// Nested: read inside-out.
$nested = \Illuminate\Support\Str::limit(\Illuminate\Support\Str::slug(trim($title)), 15, '');
// Chained: read left to right.
$chained = str($title)->trim()->slug()->limit(15, '')->toString();
var_dump($nested === $chained);
echo $chained, "\n";
// bool(true)
// the-quick-brownStringable is an object, not a string
The === row is the one that catches people, usually in a test assertion or an in_array with strict mode. Predicate methods such as contains() and length() deliberately end the chain and return scalars.
<?php
$s = str('taylor');
var_dump($s == 'taylor'); // bool(true) - loose, uses __toString
var_dump($s === 'taylor'); // bool(false) - it is an object
var_dump($s->toString() === 'taylor'); // bool(true)
// Some methods leave the chain on purpose.
var_dump($s->contains('lor')); // bool(true) - a plain bool
var_dump($s->length()); // int(6)
var_dump(get_class($s->upper())); // Stringable - still chainable
// json_encode sees an object unless you cast.
echo json_encode(['name' => (string) $s]), "\n";
// {"name":"taylor"}Conditional transforms in a chain
when() keeps a branch inside the chain instead of forcing a temporary variable and an if. The condition receives the current Stringable, so the check and the transform both stay in one expression.
<?php
$names = ['ACME_CORP', 'widgets ltd', 'Foo & Bar'];
foreach ($names as $name) {
echo str($name)
->trim()
->when(
fn ($s) => $s->upper()->exactly($s->toString()),
fn ($s) => $s->lower() // shouty input gets calmed down
)
->replace('&', 'and')
->slug(), "\n";
}
// acme-corp
// widgets-ltd
// foo-and-bar
Discussion