What's the most efficient test of whether a PHP string ends with another string?

PhpStringPerformance

Php Problem Overview


The standard PHP way to test whether a string $str ends with a substring $test is:

$endsWith = substr( $str, -strlen( $test ) ) == $test

Is this the fastest way?

Php Solutions


Solution 1 - Php

What Assaf said is correct. There is a built in function in PHP to do exactly that.

substr_compare($str, $test, strlen($str)-strlen($test), strlen($test)) === 0;

If $test is longer than $str PHP will give a warning, so you need to check for that first.

function endswith($string, $test) {
    $strlen = strlen($string);
    $testlen = strlen($test);
    if ($testlen > $strlen) return false;
    return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0;
}

Solution 2 - Php

This method is a tiny bit more memory-expensive, but it is faster:

stripos(strrev($haystack), $reversed_needle) === 0;

This is best when you know exactly what the needle is, so you can hard-code it reversed. If you reverse the needle programmatically, it becomes slower than the earlier method.

Edit (12 years later): LOL, this is a super-old answer that I wrote when I didn't know what I was actually talking about. I'd like the think I've grown since then. @DavidHarkness is right, it is not very efficient in the negative case. Probably much faster to just iterate in reverse and bail early if you really need as much perf as possible. Also, php probably has better ways to do this now. Honestly, I haven't written php in nearly a decade, so I'll leave it up to others now.

Solution 3 - Php

$endsWith = substr_compare( $str, $test, -strlen( $test ) ) === 0

Negative offset "starts counting from the end of the string".

Solution 4 - Php

Here’s a simple way to check whether one string ends with another, by giving strpos an offset right where the string should be found:

function stringEndsWith($whole, $end)
{
    return (strpos($whole, $end, strlen($whole) - strlen($end)) !== false);
}

Straightforward, and I think this’ll work in PHP 4.

Solution 5 - Php

It depends on which sort of efficiency you care about.

Your version uses more memory due to the extra copy from the use of substr.

An alternative version might search the original string for the last occurrence of the substring without making a copy, but would probably be slower due to more testing.

Probably the most efficient way is to do loop char-by-char from the -sterlen(test) position till the end of the string and compare. That's the minimal amount of comparisons you can hope to do and there's hardly any extra memory used.

Solution 6 - Php

In PHP 8:

str_ends_with('haystack', 'stack'); // true
str_ends_with('haystack', 'K'); // false

and also:

str_starts_with('haystack', 'hay'); // true

PHP RFC: Add str_starts_with(), str_ends_with() and related functions

Solution 7 - Php

Another way would be to use the strrpos function:

strrpos($str, $test) == strlen($str) - strlen($test)

But that’s not faster.

Solution 8 - Php

I hope that the below answer may be efficient and also simple:

$content = "The main string to search";
$search = "search";
//For compare the begining string with case insensitive. 
if(stripos($content, $search) === 0) echo 'Yes';
else echo 'No';

//For compare the begining string with case sensitive. 
if(strpos($content, $search) === 0) echo 'Yes';
else echo 'No';

//For compare the ending string with case insensitive. 
if(stripos(strrev($content), strrev($search)) === 0) echo 'Yes';
else echo 'No';

//For compare the ending string with case sensitive. 
if(strpos(strrev($content), strrev($search)) === 0) echo 'Yes';
else echo 'No';

Solution 9 - Php

Don't know if this is fast or not but for a single character test, these work, too:

(array_pop(str_split($string)) === $test) ? true : false;
($string[strlen($string)-1] === $test) ? true : false;
(strrev($string)[0] === $test) ? true : false;

Solution 10 - Php

easiest way to check it via regular expression

for example to check if the mail given is gmail:

echo (preg_match("/@gmail\.com$/","[email protected]"))?'true':'false';

Solution 11 - Php

I'm thinking the reverse functions like strrchr() would help you match the end of the string the fastest.

Solution 12 - Php

This is pure PHP, without calling external functions, except for strlen.

function endsWith ($ends, $string)
{
	$strLength = strlen ($string);
	$endsLength = strlen ($ends);
	for ($i = 0; $i < $endsLength; $i++)
	{
		if ($string [$strLength - $i - 1] !== $ends [$i])
			return false;
	}
	return true;
}

Solution 13 - Php

for single-char needle:

if (@strrev($haystack)[0] == $needle) {
   // yes, it ends...
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJason CohenView Question on Stackoverflow
Solution 1 - PhpmcrumleyView Answer on Stackoverflow
Solution 2 - PhpjscheelView Answer on Stackoverflow
Solution 3 - PhpOleksandr YanovetsView Answer on Stackoverflow
Solution 4 - PhpPatrick SmithView Answer on Stackoverflow
Solution 5 - PhpAssaf LavieView Answer on Stackoverflow
Solution 6 - Phpericek111View Answer on Stackoverflow
Solution 7 - PhpGumboView Answer on Stackoverflow
Solution 8 - PhpSrinivasan.SView Answer on Stackoverflow
Solution 9 - PhpwloskeView Answer on Stackoverflow
Solution 10 - PhpBiskrem MuhammadView Answer on Stackoverflow
Solution 11 - PhptkotitanView Answer on Stackoverflow
Solution 12 - PhpXesauView Answer on Stackoverflow
Solution 13 - PhpkabantejayView Answer on Stackoverflow