php string "startswith" let me count the ways

17 Oct 2007

I bounce around between half a dozen different programming languages, so I forget all the little variations. Recently I needed to test in php if a string starts with another (a prefix). So I typed in php string startswith, expecting to get the php manual with some built-in function.

oh no. It's not built in, that's fine. It's the online advice that frightens me. In order from google:

Take 1: use strstr

if (strstr($source, $prefix) == $source)) {
    echo "'$source starts with '$prefix'\n";
} else {
    echo "'$source' does not start with '$prefix'\n";
}

Uhhh if the source does not contain the prefix, then the entire string is searched. Worse then you have to do a full string compare.

Take 2: use strpos

if (strpos($source, $prefix) === 0)) {
    echo "'$source starts with '$prefix'\n";
} else {
    echo "'$source' does not start with '$prefix'\n";
}

Marginally better. Very fast if the source does start with the prefix, very slow if it does not. Lots of confusion on how to test for false (!!!) online.

Take 4: Use substr

The first example I saw just had hardwired examples, but it was something like this:

if (substr($source, 0, strlen($prefix)) == $prefix)) {
    echo "'$source starts with '$prefix'\n";
} else {
    echo "'$source' does not start with '$prefix'\n";
}

Requires creating a new string and doing a full string comparison, however it does not scan the whole string.

Take 5: Use preg_match

good grief. My favorite was this "tip" to "check if a string starts with a specific character."

   if (preg_match('/^a/', $str)) {
                echo "String starts with an a";
   }

No comment on this one.

PLEASE READ

ok team, here it is.

function str_startswith($source, $prefix)
{
   return strncmp($source, $prefix, strlen($prefix)) == 0;
}

It fails fast, it doesn't create new strings that get thrown away, it works in all cases. Granted strncmp is a bit cryptic to people who have never used "C", but it's a of shocker that I didn't see this online.

Here's my "unit test" for it.

function mytest($source, $prefix) {
    if (str_startswith($source, $prefix)) {
       echo "'$source' starts with '$prefix'\n";
    } else {
       echo "'$source' does not start with '$prefix'\n";
    }
}

mytest("foobar", "foo");
mytest("foobar", "food");
mytest("foobar", "bar");
mytest("foobar", "FOO");
mytest("foobar", "foobar1");
mytest('', '');
mytest('', 'foo');
mytest('foobar', '');

It better output:

'foobar' starts with 'foo'
'foobar' does not start with 'food'
'foobar' does not start with 'bar'
'foobar' does not start with 'FOO'
'foobar' does not start with 'foobar1'
'' starts with ''
'' does not start with 'foo'
'foobar' starts with ''

Interview Question

Since it seems that people have trouble with this, it makes a great interview question.

Here's a list of the php string functions. Write down as many functions as you can that check to see if one string starts with another. What are the pros and cons for each method? What test cases do you need to check?

Comment 2008-08-01 by None

Horrifying :).

You'll be happy to know you're the 3rd google link for 'php startswith'. Unfortunately, the 2nd is the php man page for strstr. Brutal.


Comment 2008-09-16 by None

Thank you very much for your code. I have just started with meddling with php and was trying to find a faster way to check "only" the prefix. Thanks again!


Comment 2009-03-13 by None

Actually, I did some tests and strpos is the fastest for this. The difference in speed varied depending on whether it matched or not but it was always this order:

strpos
strstr
strncmp
substr
preg_match

Test code snippet (just change if statement):

$str = 'abcdefghijk';
$search = 'abc';

echo "strstr: \t";
$start = microtime(true);
for($i=0;$i<10000000;$i++){
if(strstr($str,$search) === $str)
continue;
}
echo (microtime(true) - $start);
echo "\n";