I use the PHP function strrpos in some of my code. Last night I discovered that it behaves very strangely. The fact that it has worked this far is a miracle.

The purpose of strrpos as opposed to strpos is to find the last occurance of a substring within a string and return its index. Pretty simple.

Let’s take a look at what happens in PHP 4.4.7 (which is the default version on my web host):

$url = 'http://www.yesasia.com/en/prdTransfer.aspx/pid-1003937129/';
$lastpos = strrpos($url, 'http://');

$lastpos is, as expected, set to zero.

Now, let’s try that again:

$url = 'http://www.yesasia.com/ai-am-best-album-dvd-hong-kong-version
/1004779851-0-0-0-en/info.html';
$lastpos = strrpos($url, 'http://');

$lastpos will, of course, be zero now as well. No! It is set to 87! :o

Let’s see if we can determine what confuses the function:

$url = 'http://abc';
$lastpos = strrpos($url, 'http://'); // zero, as expected
$url = 'http://abc.html';
$lastpos = strrpos($url, 'http://'); // 11, should be zero
$url = 'http://www.yesasia.com/hal/0-aid32368-0-bpt.47-en/list.html';
$lastpos = strrpos($url, 'http://'); // 55, should be zero
$url = 'http://www.yesasia.com/hal/0-aid32368-0-bptbanana47-en
/listbanana';
$lastpos = strrpos($url, 'http://'); // 23, should be zero
$url = 'www.yesasia.com_hal_0-aid32368-0-bptbanana47-en_listbanana';
$lastpos = strrpos($url, 'http://'); // 16, should be false

If I whip up two simple substitute functions, they work as expected every single time. I have no idea what’s going on inside strrpos!

function strrpos2($h, $n)
{
  $lastpos = -1;
  while(($pos = strpos($h, $n, $lastpos + 1)) !== false)
  {
    $lastpos = $pos;
  }
  if($lastpos == -1)
    return false;
  return $lastpos;
}

function strrpos3($h, $n)
{
  $hrev = strrev($h);
  $nrev = strrev($n);
  $pos = strpos($hrev, $nrev);
  if($pos === false)
    return false;
  $lastpos = $pos - strlen($h) + strlen($n);
  return $lastpos;
}

$url = 'http://www.yesasia.com/ai-am-best-album-dvd-hong-kong-version
/1004779851-0-0-0-en/info.html';
$lastpos = strrpos($url, 'http://'); // 87
$lastpos = strrpos2($url, 'http://'); // zero
$lastpos = strrpos3($url, 'http://'); // zero