strpos

Description

Find the numeric position of the first occurrence of
needle in the haystack string.

Parameters

haystack

The string to search in.

needle

If needle is not a string, it is converted
to an integer and applied as the ordinal value of a character.

offset

If specified, search will start this number of characters counted from
the beginning of the string. If the offset is negative, the search will start
this number of characters counted from the end of the string.

Return Values

Returns the position of where the needle exists relative to the beginning of
the haystack string (independent of offset).
Also note that string positions start at 0, and not 1.

Returns FALSE if the needle was not found.

Warning

This function may
return Boolean FALSE, but may also return a non-Boolean value which
evaluates to FALSE. Please read the section on Booleans for more
information. Use the ===
operator for testing the return value of this
function.

Changelog

Version

Description

7.1.0

Support for negative offsets has been added.

Examples

// Note our use of ===. Simply == would not work as expected// because the position of 'a' was the 0th (first) character.if ($pos === false) { echo "The string '$findme' was not found in the string '$mystring'";} else { echo "The string '$findme' was found in the string '$mystring'"; echo " and exists at position $pos";}?>

// The !== operator can also be used. Using != would not work as expected// because the position of 'a' is 0. The statement (0 != false) evaluates // to false.if ($pos !== false) { echo "The string '$findme' was found in the string '$mystring'"; echo " and exists at position $pos";} else { echo "The string '$findme' was not found in the string '$mystring'";}?>

To know that a substring is in any position other than the start, you can use any of:

> 0 (recommended)!= 0 (note: but not !== 0 which also equates to FALSE)!= FALSE (disrecommended as highly confusing)

Also note that you cannot compare a value of "" to the returned value of strpos. With a loose equivalence operator (== or !=) it will return results which don't distinguish between the substring's presence versus position. With a strict equivalence operator (=== or !==) it will always return false.

It is interesting to be aware of the behavior when the treatment of strings with characters using different encodings.

<?php# Works like expected. There is no accentvar_dump(strpos("Fabio", 'b'));#int(2)

# The "á" letter is occupying two positionsvar_dump(strpos("Fábio", 'b')) ;#int(3)

# Now, encoding the string "Fábio" to utf8, we get some "unexpected" outputs. Every letter that is no in regular ASCII table, will use 4 positions(bytes). The starting point remains like before.# We cant find the characted, because the haystack string is now encoded.var_dump(strpos(utf8_encode("Fábio"), 'á'));#bool(false)

# To get the expected result, we need to encode the needle toovar_dump(strpos(utf8_encode("Fábio"), utf8_encode('á')));#int(1)

Be careful when the $haystack or $needle parameter is an integer.If you are not sure of its type, you should convert it into a string.<?php var_dump(strpos(12345,1));//falsevar_dump(strpos(12345,'1'));//0var_dump(strpos('12345',1));//falsevar_dump(strpos('12345','1'));//0$a = 12345;$b = 1;var_dump(strpos(strval($a),strval($b)));//0var_dump(strpos((string)$a,(string)$b));//0 ?>

The most straightforward way to prevent this function from returning 0 is:

strpos('x'.$haystack, $needle, 1)

The 'x' is simply a garbage character which is only there to move everything 1 position.The number 1 is there to make sure that this 'x' is ignored in the search.This way, if $haystack starts with $needle, then the function returns 1 (rather than 0).

<?php/* * A strpos variant that accepts an array of $needles - or just a string, * so that it can be used as a drop-in replacement for the standard strpos, * and in which case it simply wraps around strpos and stripos so as not * to reduce performance. * * The "m" in "strposm" indicates that it accepts *m*ultiple needles. * * Finds the earliest match of *all* needles. Returns the position of this match * or false if none found, as does the standard strpos. Optionally also returns * via $match either the matching needle as a string (by default) or the index * into $needles of the matching needle (if the STRPOSM_MATCH_AS_INDEX flag is * set). * * Case-insensitive searching can be specified via the STRPOSM_CI flag. * Note that for case-insensitive searches, if the STRPOSM_MATCH_AS_INDEX is * not set, then $match will be in the haystack's case, not the needle's case, * unless the STRPOSM_NC flag is also set. * * Flags can be combined using the bitwise or operator, * e.g. $flags = STRPOSM_CI|STRPOSM_NC */define('STRPOSM_CI' , 1); // CI => "case insensitive".define('STRPOSM_NC' , 2); // NC => "needle case".define('STRPOSM_MATCH_AS_INDEX', 4);function strposm($haystack, $needles, $offset = 0, &$match = null, $flags = 0) {// In the special case where $needles is not an array, simply wrap // strpos and stripos for performance reasons.if (!is_array($needles)) {$func = $flags & STRPOSM_CI ? 'stripos' : 'strpos';$pos = $func($haystack, $needles, $offset); if ($pos !== false) {$match = (($flags & STRPOSM_MATCH_AS_INDEX) ? 0: (($flags & STRPOSM_NC) ? $needles: substr($haystack, $pos, strlen($needles)) ) ); return $pos; } else goto strposm_no_match; }

// $needles is an array. Proceed appropriately, initially by... // ...escaping regular expression meta characters in the needles.$needles_esc = array_map('preg_quote', $needles);// If either of the "needle case" or "match as index" flags are set, // then create a sub-match for each escaped needle by enclosing it in // parentheses. We use these later to find the index of the matching // needle.if (($flags & STRPOSM_NC) || ($flags & STRPOSM_MATCH_AS_INDEX)) {$needles_esc = array_map( function($needle) {return '('.$needle.')';},$needles_esc); }// Create the regular expression pattern to search for all needles.$pattern = '('.implode('|', $needles_esc).')';// If the "case insensitive" flag is set, then modify the regular // expression with "i", meaning that the match is "caseless".if ($flags & STRPOSM_CI) $pattern .= 'i';// Find the first match, including its offset.if (preg_match($pattern, $haystack, $matches, PREG_OFFSET_CAPTURE, $offset)) {// Pull the first entry, the overall match, out of the matches array.$found = array_shift($matches);// If we need the index of the matching needle, then...if (($flags & STRPOSM_NC) || ($flags & STRPOSM_MATCH_AS_INDEX)) {// ...find the index of the sub-match that is identical // to the overall match that we just pulled out. // Because sub-matches are in the same order as needles, // this is also the index into $needles of the matching // needle.$index = array_search($found, $matches); }// If the "match as index" flag is set, then return in $match // the matching needle's index, otherwise...$match = (($flags & STRPOSM_MATCH_AS_INDEX) ? $index// ...if the "needle case" flag is set, then index into // $needles using the previously-determined index to return // in $match the matching needle in needle case, otherwise...: (($flags & STRPOSM_NC) ? $needles[$index]// ...by default, return in $match the matching needle in // haystack case.: $found[0] ) );// Return the captured offset.return $found[1]; }

A pair of functions to replace every nth occurrence of a string with another string, starting at any position in the haystack. The first works on a string and the second works on a single-level array of strings, treating it as a single string for replacement purposes (any needles split over two array elements are ignored).

Can be used for formatting dynamically-generated HTML output without touching the original generator: e.g. add a newLine class tag to every third item in a floated list, starting with the fourth item.

if you want need a fast function to find the first occurrence of any ch element of an needle array this function might be of use: <?php$eurl = strpos_needle_array($text, array('"'=>0,'\''=>0,'>'=>0, ' '=>0, "\n"=>0), $surl);

/** * Find the position of the first (partially) occurrence of a substring in a * string. * * This function is simulair to function strpos() except that it wil return a * position when the substring is partially located at the end of the string. * * @param string $haystack The string to search in. * @param mixed $needle The needle to search for. * @param integer $offset If specified, search will start this number of * characters counted from the beginning of the * string. **/function pstrpos($haystack, $needle, $offset = 0){$position = strpos($haystack, $needle, $offset); if($position !== false) { return $position; }

/** * Find the position of the first (partially) occurrence of one or more * substrings in a string. * * This function is simulair to function strpos() except that it allows to * search for multiple needles at once and it wil return a position when one of * the substrings is partially located at the end of the string. * * @param string $haystack The string to search in. * @param mixed $needles Array containing needles or string containing * needle. * @param integer $offset If specified, search will start this number of * characters counted from the beginning of the * string. * @param boolean $last If TRUE then the farthest position from the start * of one of the needles is returned. * If FALSE then the smallest position from start of * one of the needles is returned. **/function mpstrpos($haystack, $needles, $offset = 0, $last = false){ if(!is_array($needles)) { $needles = array($needles); }$found = false; foreach($needles as $needle) {$position = pstrpos($haystack, (string)$needle, $offset); if($position === false) { continue; }$exp = $last ? ($found === false || $position > $found) : ($found === false || $position < $found); if($exp) { $found = $position; } } return $found;}

Don't know if already posted this, but if I did this is an improvement.

This function will check if a string contains a needle. It _will_ work with arrays and multidimensional arrays (I've tried with a > 16 dimensional array and had no problem).

<?phpfunction str_contains($haystack, $needles){//If needles is an arrayif(is_array($needles)) {//go trough all the elementsforeach($needles as $needle) {//if the needle is also an array (ie needles is a multidimensional array)if(is_array($needle)) {//call this function againif(str_contains($haystack, $needle)) {//Will break out of loop and function.return true; }

Dan Brown and I had a discussion on the PHP list about the speed difference between the popular three string searching techniques. He wrote a simple timing test, and I adapted it further. The end result is that all three are very close and not even noticeable for sets < 1M. Although, technically strpos() is about twice as fast (as the docs allude to above). Here it is for your own amusement and testing purposes.

This function finds ALL occurrences of a substring, returning an array of indexes referring to the start of each occurrence. Overlapping subtrings are not included.<?phpfunction strpos_all($haystack, $needle) {$instances = array();

My real life problem were timestamps. I had a list of timestamps like this: "!<timestamp0>!<timestamp1>!<timestamp2>..." Then I tried to find out, wheter an actualy by "mktime()" generated timestamp is found in this list or not. But strpos() returned always boolean 0, because mktime() results are integers.

It worked only like this: strpos($timestamp_list, strval($mktime_result))

So I needed a function to check if a string contains a string. But that also works with arrays. And multidimensional arrays.

Well commented, because I'm sharing the source I use this in.

<?phpprivate static $found;//Sees if a string contains another string, WORKS WITH 2D ARRAYS! Returns true or false.public static function strcont($haystack, $needles){//If needles is an arrayif(is_array($needles)) {//go trough all the elementsforeach($needles as $needle) {//if the needle is also an array (ie needles is a multidimensional array)if(is_array($needle)) {//call this function againstatic::strcont($haystack, $needle); }//when the needle is NOT an array:elseif(strpos($haystack, $needle) !== false) {//Set the bool to true (DO NOT CHANGE TO return true). IT WILL NOT WORK!static::$found = true; } }

//Because we only set the bool if we found something we'll check if the bool is set.if(isset(static::$found)) {//Then return true.return true; }

return false; }//If the needles is not an array (this function can be used as strpos...)else { if(strpos($haystack, $needles) !== false) { return true; }

Be careful when the $haystack or $needle parameter is an integer.If you are not sure of its type, you should convert it into a string.<?php var_dump(strpos(12345,1));//falsevar_dump(strpos(12345,'1'));//0var_dump(strpos('12345',1));//falsevar_dump(strpos('12345','1'));//0$a = 12345;$b = 1;var_dump(strpos(strval($a),strval($b)));//0var_dump(strpos((string)$a,(string)$b));//0

&nbspClick here to go to the support pages.Click here to submit a bug report.Click here to request a feature.(Again, please note, if you ask a question, report a bug, or request a feature, your note will be deleted.)