Str::endsWith
Determines whether a string ends with a given value, or with any value from an array.
Str::endsWith(string $haystack, string|iterable<string> $needles): boolParameters
| Parameter | Type | Description |
|---|---|---|
$$haystack | string | The string to test. |
$$needles | string|iterable<string> | A single suffix, or any iterable of suffixes. The method returns true as soon as one of them matches. |
Return value
booltrue if $haystack ends with at least one of the given needles; false otherwise, including when $haystack is null, when $needles is empty, and when every needle is an empty string.
Errors
Nothing. A null haystack returns false rather than raising a TypeError.
Str::endsWith wraps PHP's str_ends_with() and adds two things: it accepts an iterable of suffixes, and it returns false for a null haystack instead of throwing.
When to reach for it
Use it for suffix tests where several endings are acceptable — an upload whose name must end in one of ['.jpg', '.jpeg', '.png'], a path that may or may not already carry a trailing slash, a class name ending in Controller or Job. Passing the array replaces a chain of || and short-circuits on the first match.
What trips people up
Unlike Str::contains and Str::is, this method has no ignoreCase argument. A file uploaded as report.PDF fails Str::endsWith($name, '.pdf'), which is the single most common bug in extension checks written with it. Either lower-case the haystack yourself, or reach for Str::is('*.pdf', $name, ignoreCase: true).
Empty needles are skipped, so Str::endsWith('anything', '') is false where the native str_ends_with() is true. And do not use it for security decisions on filenames — extension checks are a convenience, not validation; verify the actual MIME type.
Example
When to use it
- Accept an upload only when its filename ends in one of several image extensions.
- Detect whether a base URL already carries a trailing slash before joining a path.
- Route a class name by its suffix, such as anything ending in Controller or Job.
Frequently asked questions
Is Str::endsWith case insensitive?
No, and it has no ignoreCase argument. Lower-case the haystack with Str::lower() first, or use Str::is('*.ext', $value, ignoreCase: true).
Can Str::endsWith check several suffixes at once?
Yes. Pass an array or any iterable as the second argument and it returns true as soon as one of them matches the end of the string.
Why does Str::endsWith return false for an empty needle?
Empty needles are skipped by design, unlike PHP's native str_ends_with() which treats '' as always matching. Validate the needle before calling if it can be blank.
More examples
A case-safe extension check
Lowering the haystack once, rather than duplicating every extension in upper case, is what makes holiday.JPG pass. The extension list itself stays lower-case and readable.
<?php
use Illuminate\Support\Str;
$images = ['.jpg', '.jpeg', '.png', '.webp'];
$uploads = ['holiday.JPG', 'diagram.png', 'notes.txt'];
foreach ($uploads as $name) {
$ok = Str::endsWith(Str::lower($name), $images);
echo str_pad($name, 14), var_export($ok, true), "\n";
}
// holiday.JPG true
// diagram.png true
// notes.txt falseThe same test with Str::is
When case-insensitivity is required, Str::is with a leading asterisk does the job endsWith cannot, at the cost of compiling a small regex per pattern. For hot loops, lower-casing once and using endsWith is faster.
<?php
use Illuminate\Support\Str;
$name = 'holiday.JPG';
// endsWith cannot ignore case...
var_dump(Str::endsWith($name, '.jpg')); // false
// ...but Str::is can, using an asterisk wildcard.
var_dump(Str::is('*.jpg', $name, ignoreCase: true)); // true
// And it accepts a list of patterns too.
var_dump(Str::is(['*.jpg', '*.png'], $name, ignoreCase: true)); // true
Discussion