Hudzilla.org - the homepage of Paul Hudson
Contents > Functions > Playing with strings Wish List | Report Bug | About Me ]

4.7.5     Finding a string within a string: strpos() and stripos()

This is NOT the latest copy of this book; click here for the latest version.

int strpos ( string haystack, string needle [, int offset])

int stripos ( string haystack, string needle [, int offset])

Strpos(), and its case-insensitive sibling stripos(), returns the index of the first occurrence of a substring within a string. It is easier to explain in code, so here goes:

<?php
    $string
= "This is a strpos() test";
    print
strpos($string, "a") . "\n";
?>

That will return 8, because the first character in "This is a strpos() test" that is a lowercase A is at index 8. Remember that PHP considers the first letter of a string to be index 0, which means that the A strpos() found is actually the ninth character.

You can specify whole words in parameter two, which will make strpos() return the first position of that word within the string, for example strpos($string, "test") would return 19 - the index of the first letter in the matched word.

If the substring sent in parameter two is not found in parameter one, strpos() will return false. Consider this script:

<?php
    $string
= "This is a strpos() test";
    
$pos = strpos($string, "This");
    if (
$pos == false) {
        print
"Not found\n";
    } else {
        print
"Found!\n";
    }
?>

If you try executing that, you will find that it outputs "Not found", despite "This" quite clearly being in $string. Is it another case sensitivity problem? Not quite. This time the problem lies in the fact that "This" is the first thing in $string, which means that strpos() will return 0. However, PHP considers 0 to be the same value as false, which means that our if statement cannot tell the difference between "Substring not found" and "Substring found at index 0" - quite a problem!

Luckily, PHP comes to the rescue with the === operator, which, if you recall, means "is identical to", which means $pos must be equal to false and of the same type as false (boolean). If the "This" is found in $string, strpos()will return 0, but it will be of type integer . If we change our if statement to use === rather than ==, PHP will check the value of 0 and false and find they match (both false), then check the types of 0 and false, and find that they do not match - the former is an integer, and the latter is a boolean.

So, the corrected version of the script is this:

<?php
    $string
= "This is a strpos() test";
    
$pos = strpos($string, "This");
    if (
$pos === false) {
        print
"Not found\n";
    } else {
        print
"Found!\n";
    }
?>

Now, consider this next script, which tries to match the "i" in "is":

<?php
    $string
= "This is a strpos() test";
    
$pos = strpos($string, "i");
    if (
$pos === false) {
        print
"Not found\n";
    } else {
        print
"Found at $pos!\n";
    }
?>

The problem there is that strpos() matches the first "i" it comes across, which will be in "This". Fortunately there is a third parameter to strpos() that allows us to specify where to start from. As the "i" in "This" is at index 2, we just need to specify one place after that (3) as the start position for strpos(), and it will report back the next "i" after it. For example:

<?php
    $string
= "This is a strpos() test";
    
$pos = strpos($string, "i", 3);
    if (
$pos === false) {
        print
"Not found\n";
    } else {
        print
"Found at $pos!\n";
    }
?>

This time that will print "found at 5!", which is the position of the "i" in "is".





<< 4.7.4 Measuring strings: strlen(), count_chars(), and str_word_count()   4.7.6 Returning the first occurrence of a string: strstr() and stristr() >>
Table of Contents
Want to see this stuff in print? PHP in a Nutshell takes the core topics covered here, adds in thousands of edits from the editorial team and myself, and combines them to make an unbeatable reference for PHP programmers at all levels.



My latest book has hundreds more tips on how to use PHP, Apache, and MySQL, plus Perl, Python, shell scripts, performance tuning, and more!



Top-right shadow
 
Bottom-left shadow Bottom shadow

Comments from other readers
A PHP User - 05 Dec 2008

I found it quite useful for looking for certain xml tags returned by Twitter's API as shown below. The API doesn't return a "success" or an "error" tag but does return a created at tag that exists upon successful post and a string that says "Could not authenticate you" upon password failure. This was a real quick way of determining whether or not the post worked and if not, was it the password that caused it. In the code below, $buffer contains the result XML that is sent by twitter.


$pos = strpos($buffer, "<created_at>");
if ($pos === false)
{
$pos= strpos($buffer, "Could not authenticate you");
if ($pos === false)
{
echo "Something has failed and it's not your password.";
}
else
{
echo "Password failure. Please check your settings.";
}
}
else
{
print "Post successful!";
}

A PHP User - 05 Dec 2008

http://www.kg

jcastro - 05 Dec 2008

nice example, this is covered in most php conversations of "common errors", learn to use === and ==.

Here is another example solution i just thought of.

if(is_numeric(strpos("This World","This")))
{
echo 'Found This';
}
else
{
echo 'Nothing Found'
}

Ed ed [at] edsadesigns.com - 05 Dec 2008

I've used this function to work out which strings are 'Special Delivery' and which are not... For example, I have a list of delivery options for my ecommerce site, and I want to just pick out the Special Delivery ones:

$aDeliveryMethod[] = UK Mainland & IOW/Royal Mail
$aDeliveryMethod[] = UK Mainland & IOW/Special Delivery
$aDeliveryMethod[] = Northern Ireland/Royal Mail
$aDeliveryMethod[] = Northern Ireland/Special Delivery
$aDeliveryMethod[] = Channel Islands/Royal Mail
$aDeliveryMethod[] = Channel Islands/Special Delivery

foreach($aDeliveryMethod as $iKey=>$sValue){
$pos = strpos($sValue, "Special Delivery");
if ($pos === false) {
$sDirectFeed .= 'RMRFC'; // This is a normal one
} else {
$sDirectFeed .= 'RMSD1'; // This is a special delivery one
}
}

My example may not be that clear, but it's just to demonstrate that this function is useful.

A PHP User - 05 Dec 2008

when you design a membership login system, you would find it useful to check the authorization level of user.

A PHP User - 05 Dec 2008

I have a use for this: My brother wants to have an option for wordpress which allows him to produce a smaller title than regular. Probably the easiest way to do this would be to have a comemnted 'smalltitle' at the start of the post, something which this code would be useful for.

cast3r - 05 Dec 2008

eh, so open php.net and check those functions there - ull see
theres a lot of real-life examples in comments.

A |\| 3 \/\/ 13 | E PHP User - 05 Dec 2008

I don't see why we would need this either :-\

Semper Fi - 05 Dec 2008

I am still not grasping why we would use these functions? An example of real world use would be beneficial.

-D

raevans@tlchealth,net - 05 Dec 2008

Your use of "errors" to explain PHP is probably the most helpful point throughout this book. Thanks



Add comment
Please note that by posting a comment here you are committing it to the public domain. This is important so that others can make use of your code themselves, and also so that I can incorporate helpful notes directly into the main text. Comments are limited to 2000 characters in length.

If you are reporting an error in the content, please tell me directly.

Your name/email address:
Your comment:
 
Now, in order to verify that you're a real person, please answer this simple question: what is five plus one?
The answer is:
(please write in
numbers, eg 19)


Top-right shadow
 
Bottom-left shadow Bottom shadow