Documentation on substr

substr = Return part of a string

Returns the portion of string specified by the start and length parameters.

string The input string. Must be one character or longer. start If start is non-negative, the returned string will start at the start'th position in string, counting from zero. For instance, in the string 'abcdef', the character at position 0 is 'a', the character at position 2 is 'c', and so forth. If start is negative, the returned string will start at the start'th character from the end of string. If string is less than start characters long, FALSE will be returned. Example #1 Using a negative start <?php$rest = substr("abcdef", -1);    // returns "f"$rest = substr("abcdef", -2);    // returns "ef"$rest = substr("abcdef", -3, 1); // returns "d"?> length If length is given and is positive, the string returned will contain at most length characters beginning from start (depending on the length of string). If length is given and is negative, then that many characters will be omitted from the end of string (after the start position has been calculated when a start is negative). If start denotes the position of this truncation or beyond, FALSE will be returned. If length is given and is 0, FALSE or NULL, an empty string will be returned. If length is omitted, the substring starting from start until the end of the string will be returned. Example #2 Using a negative length <?php$rest = substr("abcdef", 0, -1);  // returns "abcde"$rest = substr("abcdef", 2, -1);  // returns "cde"$rest = substr("abcdef", 4, -4);  // returns false$rest = substr("abcdef", -3, -1); // returns "de"?>

Usage, params, and more on substr

string substr ( string $string , int $start [, int $length ] )

string The input string. Must be one character or longer. start If start is non-negative, the returned string will start at the start'th position in string, counting from zero. For instance, in the string 'abcdef', the character at position 0 is 'a', the character at position 2 is 'c', and so forth. If start is negative, the returned string will start at the start'th character from the end of string. If string is less than start characters long, FALSE will be returned. Example #1 Using a negative start <?php$rest = substr("abcdef", -1);    // returns "f"$rest = substr("abcdef", -2);    // returns "ef"$rest = substr("abcdef", -3, 1); // returns "d"?> length If length is given and is positive, the string returned will contain at most length characters beginning from start (depending on the length of string). If length is given and is negative, then that many characters will be omitted from the end of string (after the start position has been calculated when a start is negative). If start denotes the position of this truncation or beyond, FALSE will be returned. If length is given and is 0, FALSE or NULL, an empty string will be returned. If length is omitted, the substring starting from start until the end of the string will be returned. Example #2 Using a negative length <?php$rest = substr("abcdef", 0, -1);  // returns "abcde"$rest = substr("abcdef", 2, -1);  // returns "cde"$rest = substr("abcdef", 4, -4);  // returns false$rest = substr("abcdef", -3, -1); // returns "de"?>

Returns the extracted part of string; or FALSE on failure, or an empty string.

Returns FALSE on error. <?phpvar_dump(substr('a', 2)); // bool(false)?>

Notes and warnings on substr

Basic example of how to use: substr

Example #3 Basic substr() usage

<?php
echo substr('abcdef'1);     // bcdef
echo substr('abcdef'13);  // bcd
echo substr('abcdef'04);  // abcd
echo substr('abcdef'08);  // abcdef
echo substr('abcdef', -11); // f

// Accessing single characters in a string
// can also be achieved using "square brackets"
$string 'abcdef';
echo 
$string[0];                 // a
echo $string[3];                 // d
echo $string[strlen($string)-1]; // f

?>

Example #4 substr() casting behaviour

<?php
class apple {
    public function 
__toString() {
        return 
"green";
    }
}

echo 
"1) ".var_export(substr("pear"02), true).PHP_EOL;
echo 
"2) ".var_export(substr(5432102), true).PHP_EOL;
echo 
"3) ".var_export(substr(new apple(), 02), true).PHP_EOL;
echo 
"4) ".var_export(substr(true01), true).PHP_EOL;
echo 
"5) ".var_export(substr(false01), true).PHP_EOL;
echo 
"6) ".var_export(substr(""01), true).PHP_EOL;
echo 
"7) ".var_export(substr(1.2e304), true).PHP_EOL;
?>

Output of the above example in PHP 7:

 1) 'pe' 2) '54' 3) 'gr' 4) '1' 5) '' 6) '' 7) '1200' 

Output of the above example in PHP 5:

 1) 'pe' 2) '54' 3) 'gr' 4) '1' 5) false 6) false 7) '1200' 

Other code examples of substr being used

For getting a substring of UTF-8 characters, I highly recommend mb_substr

<?php
        $utf8string
= "cakeæøå";

        echo
substr($utf8string,0,5);
       
// output cake#
       
echo mb_substr($utf8string,0,5,'UTF-8');
       
//output cakeæ
?>

may be by following functions will be easier to extract the needed sub parts from a string:

<?php
after
('@', 'biohazard@online.ge');
//returns 'online.ge'
//from the first occurrence of '@'

before ('@', 'biohazard@online.ge');
//returns 'biohazard'
//from the first occurrence of '@'

between ('@', '.', 'biohazard@online.ge');
//returns 'online'
//from the first occurrence of '@'

after_last ('[', 'sin[90]*cos[180]');
//returns '180]'
//from the last occurrence of '['

before_last ('[', 'sin[90]*cos[180]');
//returns 'sin[90]*cos['
//from the last occurrence of '['

between_last ('[', ']', 'sin[90]*cos[180]');
//returns '180'
//from the last occurrence of '['
?>

here comes the source:

<?php

   
function after ($this, $inthat)
    {
        if (!
is_bool(strpos($inthat, $this)))
        return
substr($inthat, strpos($inthat,$this)+strlen($this));
    };

    function
after_last ($this, $inthat)
    {
        if (!
is_bool(strrevpos($inthat, $this)))
        return
substr($inthat, strrevpos($inthat, $this)+strlen($this));
    };

    function
before ($this, $inthat)
    {
        return
substr($inthat, 0, strpos($inthat, $this));
    };

    function
before_last ($this, $inthat)
    {
        return
substr($inthat, 0, strrevpos($inthat, $this));
    };

    function
between ($this, $that, $inthat)
    {
        return
before ($that, after($this, $inthat));
    };

    function
between_last ($this, $that, $inthat)
    {
     return
after_last($this, before_last($that, $inthat));
    };

// use strrevpos function in case your php version does not include it
function strrevpos($instr, $needle)
{
   
$rev_pos = strpos (strrev($instr), strrev($needle));
    if (
$rev_pos===false) return false;
    else return
strlen($instr) - $rev_pos - strlen($needle);
};
?>

Anyone coming from the Python world will be accustomed to making substrings by using a "slice index" on a string.  The following function emulates basic Python string slice behavior. (A more elaborate version could be made to support array input as well as string, and the optional third "step" argument.)

<?php

function py_slice($input, $slice) {
   
$arg = explode(':', $slice);
   
$start = intval($arg[0]);
    if (
$start < 0) {
       
$start += strlen($input);
    }
    if (
count($arg) === 1) {
        return
substr($input, $start, 1);
    }
    if (
trim($arg[1]) === '') {
        return
substr($input, $start);
    }
   
$end = intval($arg[1]);
    if (
$end < 0) {
       
$end += strlen($input);
    }
    return
substr($input, $start, $end - $start);
}

print
py_slice('abcdefg', '2') . "\n";
print
py_slice('abcdefg', '2:4') . "\n";
print
py_slice('abcdefg', '2:') . "\n";
print
py_slice('abcdefg', ':4') . "\n";
print
py_slice('abcdefg', ':-3') . "\n";
print
py_slice('abcdefg', '-3:') . "\n";

?>

The $slice parameter can be a single character index, or a range separated by a colon. The start of the range is inclusive and the end is exclusive, which may be  counterintuitive. (Eg, py_slice('abcdefg', '2:4') yields 'cd' not 'cde'). A negative range value means to count from the end of the string instead of the beginning. Both the start and end of the range may be omitted; the start defaults to 0 and the end defaults to the total length of the input.

The output from the examples:
c
cd
cdefg
abcd
abcd
efg

Hmm ... this is a script I wrote, whitch is very similar to substr, but it isn't takes html and bbcode for counting and it takes portion of string and show avoided (html & bbcode) tags too ;]
Specially usefull for show part of serach result included html and bbcode tags

<?php

/**
* string csubstr ( string string, int start [, int length] )
*
* @author FanFataL
* @param string string
* @param int start
* @param [int length]
* @return string
*/
function csubstr($string, $start, $length=false) {
   
$pattern = '/(\[\w+[^\]]*?\]|\[\/\w+\]|<\w+[^>]*?>|<\/\w+>)/i';
   
$clean = preg_replace($pattern, chr(1), $string);
    if(!
$length)
       
$str = substr($clean, $start);
    else {
       
$str = substr($clean, $start, $length);
       
$str = substr($clean, $start, $length + substr_count($str, chr(1)));
    }
   
$pattern = str_replace(chr(1),'(.*?)',preg_quote($str));
    if(
preg_match('/'.$pattern.'/is', $string, $matched))
        return
$matched[0];
    return
$string;
}

?>

Using this is similar to simple substr.

Greatings ;]
...

<?Php

### SUB STRING  BY WORD USING substr() and strpos()  #####

### THIS SCRIPT WILL RETURN PART OF STRING  WITHOUT WORD BREAK ###

$description = ‘your description here your description here your description here your description here your description here your description here your description hereyour description here your description here’  // your description here .

$no_letter = 30 ;

if(
strlen($desctiption) > 30 )
{
     echo
substr($description,0,strpos($description,’ ‘,30));             //strpos to find ‘ ‘ after 30 characters.
}
else {
     echo
$description;
}

?>

I have developed a function with a similar outcome to jay's

Checks if the last character is or isnt a space. (does it the normal way if it is)
It explodes the string into an array of seperate works, the effect is... it chops off anything after and including the last space.

<?php
function limit_string($string, $charlimit)
{
    if(
substr($string,$charlimit-1,1) != ' ')
    {
       
$string = substr($string,'0',$charlimit);
       
$array = explode(' ',$string);
       
array_pop($array);
       
$new_string = implode(' ',$array);

        return
$new_string.'...';
    }
    else
    {   
        return
substr($string,'0',$charlimit-1).'...';
    }
}
?>

This function can replace substr() in some situations you don't want to cut right in the middle of a word. strtrim will cut between words when it is possible choosing the closest possible final string len to return. the maxoverflow parameter lets you choose how many characters can overflow past the maxlen parameter.

<?php

function strtrim($str, $maxlen=100, $elli=NULL, $maxoverflow=15) {
    global
$CONF;
       
    if (
strlen($str) > $maxlen) {
           
        if (
$CONF["BODY_TRIM_METHOD_STRLEN"]) {
            return
substr($str, 0, $maxlen);
        }
           
       
$output = NULL;
       
$body = explode(" ", $str);
       
$body_count = count($body);
       
       
$i=0;
   
        do {
           
$output .= $body[$i]." ";
           
$thisLen = strlen($output);
           
$cycle = ($thisLen < $maxlen && $i < $body_count-1 && ($thisLen+strlen($body[$i+1])) < $maxlen+$maxoverflow?true:false);
           
$i++;
        } while (
$cycle);
        return
$output.$elli;
    }
    else return
$str;
}

?>

Here we have gr8 function which simply convert ip address to a number using substr with negative offset.
You can need it if you want to compare some IP addresses converted to a numbers.
For example when using ip2country, or eliminating same range of ip addresses from your website :D

<?php

function ip2no($val)
{   
    list(
$A,$B,$C,$D)    =    explode(".",$val);
    return
       
substr("000".$A,-3).
       
substr("000".$B,-3).
       
substr("000".$C,-3).
       
substr("000".$D,-3);
}

$min        =    ip2no("10.11.1.0");
$max        =    ip2no("111.11.1.0");
$visitor    =    ip2no("105.1.20.200");

if(
$min<$visitor && $visitor<$max)   
    {    echo
'Welcome !';    }
else   
    {    echo
'Get out of here !';    }

?>

Truncate a float number. Similar to the Excel trunc function.

<?php
function truncate_number($val,$decimals=2){
   
       
$number=array();
       
$number=explode(".",$val);           
       
$result=0;

        if (
count($number)>1){

           
$result = $number[0] . "." . substr($number[1],0,$decimals); 
           
        } else {
       
           
$result = $val;
           
        }               

        unset(
$number);

        return
$result;   
}

echo
truncate_number(99.123456,2); //result = 99.12
echo truncate_number(99.123456,5); //result = 99.12345
echo truncate_number(99.123456,1); //result = 99.1
?>

Adding the $limit parameter introduced a bug that was not present in the original. If $limit is small or negative, a string with a length exceeding the limit can be returned. The $limit parameter should be checked. It takes slightly more processing, but it is dwarfed in comparison to the use of strlen().

<?php
 
function short_name($str, $limit)
  {
   
// Make sure a small or negative limit doesn't cause a negative length for substr().
   
if ($limit < 3)
    {
     
$limit = 3;
    }

   
// Now truncate the string if it is over the limit.
   
if (strlen($str) > $limit)
    {
      return
substr($str, 0, $limit - 3) . '...';
    }
    else
    {
      return
$str;
    }
  }
?>

Regarding the utf8_substr function from lmak: The pattern '/./u' doesn't match newline characters. This means that the substring from 0 to the total length of the string will miss the number of characters in the end matching the number of newlines in the string. To fix this one can add the s modifier (PCRE_DOTALL) in the pattern:

<?php
function utf8_substr($str,$start)
{
  
preg_match_all("/./su", $str, $ar);

   if(
func_num_args() >= 3) {
      
$end = func_get_arg(2);
       return
join("",array_slice($ar[0],$start,$end));
   } else {
       return
join("",array_slice($ar[0],$start));
   }
}
?>

<?php

//removes string from the end of other

function removeFromEnd($string, $stringToRemove) {
   
$stringToRemoveLen = strlen($stringToRemove);
   
$stringLen = strlen($string);
   
   
$pos = $stringLen - $stringToRemoveLen;

   
$out = substr($string, 0, $pos);

    return
$out;
}

$string = 'picture.jpg.jpg';
$string = removeFromEnd($string, '.jpg');
?>

[English]
I created python similar accesing list or string with php substr & strrev functions.

Use: str($string,$pattern)

About the python pattern,
http://docs.python.org/release/1.5.1p1/tut/strings.html
http://effbot.org/zone/python-list.htm

About of pattern structures
[start:stop:step]

Example,
<?php
$s
= "fatihmertdogancan";
echo
str($s,"1:9:-2");
echo
"<br/>";
echo
str($s,"1:-3:-2");
echo
"<br/>";
echo
str($s,"1:-11:-5");
echo
"<br/>";
echo
str($s,"1:9:4");
?>

Output,
thetoacn
eht
aom
htan

This is function phpfiddle link: http://phpfiddle.org/main/code/e82-y5d

or source;

<?php
   
function str($str,$pattern){
       
//[start:stop:step]
        //pattern ->            ([-]?[0-9]*|\s):([-]?[0-9]*|\s):([-]?[0-9]*|\s)
       
preg_match("/([-]?[0-9]*|\s?):([-]?[0-9]*|\s?):?([-]?[0-9]*|\s?)/", $pattern, $yakala);
       
$start = $yakala[1];
       
$stop = $yakala[2];
       
$step = $yakala[3];
       
        if(empty(
$start) && empty($stop) && $step == "-1"){//istisna durum
           
return strrev($str);
        }else if(empty(
$start) && empty($stop) && isset($step)){//istisna durum
           
$rev = "";
           
$yeni = "";
            if(
$step[0] == "-" && $stop != "-1"){$rev = "VAR";}
           
$atla = abs($step);
            for(
$i = 0; $i <= strlen($str); $i++){
               
$offset = $i*$atla;
                if(isset(
$str[$offset])){
                   
$yeni = $yeni.$str[$offset];
                }
            }
            if(
$rev != "VAR"){
                return
substr($yeni,0,strlen($str)-1);
               
//"hepsi boÅŸ, step dolu o da +";
           
}else{
                return
strrev(substr($yeni,0,strlen($str)-1));
               
//"hepsi boÅŸ, step dolu o da -";
           
}
        }
       
        if(empty(
$start) && empty($stop) && empty($step)){
            return
$str;
           
//"hepsi boÅŸ";
       
}else if(empty($start)){
            if(isset(
$stop) && empty($step)){
               
$rev = "";
                if(
$stop[0] == "-"){$rev = "VAR";}
                if(
$rev != "VAR"){
                    return
substr($str,0,$stop);
                   
//"start ve step boÅŸ, stop dolu"
               
}else{
                    return
strrev(substr($str,0,$stop));
                   
//"start ve step boÅŸ, stop -1";
               
}
            }else if(isset(
$stop) && isset($step)){
               
$rev = "";
                if(
$stop[0] == "-"){$rev = "VAR";}
               
$yeni = "";
                if(
$step == 1){
                    if(
$rev != "VAR"){
                        return
$str;
                       
//"start boÅŸ, stop ve step dolu, step 1";
                   
}else{
                        return
strrev(substr($str,0,abs($stop))); //abs -> mutlak deÄŸer (-5 = 5)
                        //"start boÅŸ, stop -, step dolu, step 1";
                   
}
                }else{
                   
$atla = abs($step);
                    for(
$i = 0; $i <= strlen($str); $i++){
                       
$offset = $i*$atla;
                        if(isset(
$str[$offset])){
                           
$yeni = $yeni.$str[$offset];
                        }
                    }
                    if(
$rev != "VAR"){
                        return
substr($yeni,0,$stop);
                       
//"start boÅŸ, step ve stop dolu";
                   
}else{
                        return
strrev(substr($yeni,0,abs($stop)));
                       
//"start boÅŸ, step ve stop -";
                   
}
                }
            }
       
//start boÅŸ deÄŸilse
       
}else if(!empty($start)){
            if(isset(
$stop) && empty($step)){
               
$rev = "";
                if(
$stop[0] == "-"){$rev = "VAR";}
                if(
$rev != "VAR"){
                    return
substr($str,$start,$stop);
                   
//return "step boÅŸ, start ve stop dolu";
               
}else{
                    return
strrev(substr($str,0,abs($stop)));
                   
//"step boÅŸ, start ve stop dolu, stop -";
               
}
            }else if(isset(
$stop) && isset($step)){
               
               
//hepsi dolu
               
$rev = "";
                if(
$stop[0] == "-"){$rev = "VAR";}
               
$yeni = "";
                if(
$step == 1){
                    if(
$rev != "VAR"){
                        return
substr($str,$start,$stop);
                       
//"hepsi dolu, step 1";
                   
}else{
                        return
substr($str,$start,abs($stop));
                       
//"hepsi dolu, step 1, stop -";
                   
}
                }else{
                    if(
$stop[0] == "-"){$rev = "VAR";}
                   
$atla = abs($step);
                    for(
$i = 0; $i <= strlen($str); $i++){
                       
$offset = $i*$atla;
                        if(isset(
$str[$offset])){
                           
$yeni = $yeni.$str[$offset];
                        }
                    }
                    if(
$rev != "VAR"){
                        return
substr($yeni,$start,$stop);
                       
//"hepsi dolu";
                   
}else{
                        return
strrev(substr($yeni,$start,abs($stop)));
                       
//"hepsi dolu, stop -";
                   
}
                }
            }
        }
    }
?>

Good works..

Just a little function to cut a string by the wanted amount. Works in both directions.

<?php
function cutString($str, $amount = 1, $dir = "right")
{
  if((
$n = strlen($str)) > 0)
  {
    if(
$dir == "right")
    {
     
$start = 0;
     
$end = $n-$amount;
    } elseif(
$dir == "left") {
     
$start = $amount;
     
$end = $n;
    }
   
    return
substr($str, $start, $end);
  } else return
false;
}
?>

Enjoy ;)

If you need just a single character from the string you don't need to use substr(), just use curly braces notation:

<?php
   
// both lines will output the 3rd character
   
echo substr($my_string, 2, 1);
    echo
$my_string{2}; 
?>

curly braces syntax is faster and more readable IMHO..

I wanted to work out the fastest way to get the first few characters from a string, so I ran the following experiment to compare substr, direct string access and strstr:

<?php
/* substr access */
beginTimer();
for (
$i = 0; $i < 1500000; $i++){
   
$opening = substr($string,0,11);
    if (
$opening == 'Lorem ipsum'){
       
true;
    }else{
       
false;
    }
}
$endtime1 = endTimer();

/* direct access */
beginTimer();
for (
$i = 0; $i < 1500000; $i++){
    if (
$string[0] == 'L' && $string[1] == 'o' && $string[2] == 'r' && $string[3] == 'e' && $string[4] == 'm' && $string[5] == ' ' && $string[6] == 'i' && $string[7] == 'p' && $string[8] == 's' && $string[9] == 'u' && $string[10] == 'm'){
       
true;
    }else{
       
false;
    }
}
$endtime2 = endTimer();

/* strstr access */
beginTimer();
for (
$i = 0; $i < 1500000; $i++){
   
$opening = strstr($string,'Lorem ipsum');
    if (
$opening == true){
       
true;
    }else{
       
false;
    }
}
$endtime3 = endTimer();

echo
$endtime1."\r\n".$endtime2."\r\n".$endtime3;
?>

The string was 6 paragraphs of Lorem Ipsum, and I was trying match the first two words. The experiment was run 3 times and averaged. The results were:

(substr) 3.24
(direct access) 11.49
(strstr) 4.96

(With standard deviations 0.01, 0.02 and 0.04)

THEREFORE substr is the fastest of the three methods for getting the first few letters of a string.

Add on to (a function originally written by) "Matias from Argentina": str_format_number function.

Just added handling of $String shorter then $Format by adding a side to start the fill and a string length to the while loop.

<?php
function str_format_number($String, $Format, $Start = 'left'){
   
//If we want to fill from right to left incase string is shorter then format
   
if ($Start == 'right') {
       
$String = strrev($String);
       
$Format = strrev($Format);
    }
    if(
$Format == '') return $String;
    if(
$String == '') return $String;   
   
$Result = '';
   
$FormatPos = 0;
   
$StringPos = 0;
    while ((
strlen($Format) - 1) >= $FormatPos && strlen($String) > $StringPos) {
       
//If its a number => stores it
       
if (is_numeric(substr($Format, $FormatPos, 1))) {
           
$Result .= substr($String, $StringPos, 1);
           
$StringPos++;
           
//If it is not a number => stores the caracter
       
} else {
           
$Result .= substr($Format, $FormatPos, 1);
        }
       
//Next caracter at the mask.
       
$FormatPos++;
    }
    if (
$Start == 'right') $Result = strrev($Result);
    return
$Result;
}
?>

Using a 0 as the last parameter for substr().

As per examples
<?php $var = substr($var, 4); ?>

works no problem. However
<?php $var = substr($var, 4, 0); ?>

will get you nothing. Just a quick heads up

You might expect substr('123456', 6) to return an empty string. Instead it returns boolean FALSE.

This behavior should be mentioned in the Return Values section of the manual. Instead it is only mentioned in the Parameters section.

If you need an empty string instead of a boolean FALSE you should typecast the result to a string.

<?php
$a
= substr('123456', 6);              // equivalent to $a = FALSE
$a = (string) substr('123456', 6);   // equivalent to $a = '';
?>

I needed a function like lpad from oracle, or right from SQL
then I use this code :

<?php
function right($string,$chars)
{
   
$vright = substr($string, strlen($string)-$chars,$chars);
    return
$vright;
   
}

    echo
right('0r0j4152',4);
?>

Result:
4152
------------------------------------------------
This function is really simple, I just wanted to share, maybe helps someone out there. 

regards,

Split a string to an array of strings specified by an array of lengths:

<?php
function split_by_lengths($inString, $arrayLengths)
{
   
$output = array();
    foreach (
$arrayLengths as $oneLength)
    {
       
$output[] = substr($inString, 0, $oneLength);
       
$inString = substr($inString, $oneLength);
    }
    return (
$output);
}
?>
split_by_lengths('teststringtestteststring', array(4,6,4,4,6)) returns:
array('test','string','test','test','string')

Don't use it on user input without some error handling!

Well this is a script I wrote, what it does is chop up long words with malicious meaning into several parts. This way, a chat in a table will not get stretched anymore.

<?php

function text($string,$limit=20,$chop=10){

$text = explode(" ",$string);
while(list(
$key, $value) = each($text)){
   
$length = strlen($value);
    if(
$length >=20){
        for(
$i=0;$i<=$length;$i+=10){
           
$new .= substr($value, $i, 10);
           
$new .= " ";
        }
        
$post .= $new;
    }
    elseif(
$length <=15){
       
$post .= $value;
    }
   
$post .= " ";
}
return(
$post);
}

// for example, this would return:
$output = text("Well this text doesn't get cut up, yet thisssssssssssssssssssssssss one does.", 10, 5);

echo(
$output); // "Well this text doesn't get cup up, yet thiss sssss sssss sssss sssss sss one does."
?>

I hope it was useful.. :)

<?php

/**
* string substrpos(string $str, mixed $start [[, mixed $end], boolean $ignore_case])
*
* If $start is a string, substrpos will return the string from the position of the first occuring $start to $end
*
* If $end is a string, substrpos will return the string from $start to the position of the first occuring $end
*
* If the first character in (string) $start or (string) $end is '-', the last occuring string will be used.
*
* If $ignore_case is true, substrpos will not care about the case.
* If $ignore_case is false (or anything that is not (boolean) true, the function will be case sensitive.
*        Both of the above: only applies if either $start or $end are strings.
*
* echo substrpos('This is a string with 0123456789 numbers in it.', 5, '5');
*        // Prints 'is a string with 01234';
*
* echo substrpos('This is a string with 0123456789 numbers in it.', '5', 5);
*        // Prints '56789'
*
* echo substrpos('This is a string with 0123456789 numbers in it and two strings.', -60, '-string')
*        // Prints 's is a string with 0123456789 numbers in it and two '
*
* echo substrpos('This is a string with 0123456789 numbers in it and two strings.', -60, '-STRING', true)
*        // Prints 's is a string with 0123456789 numbers in it and two '
*
* echo substrpos('This is a string with 0123456789 numbers in it and two strings.', -60, '-STRING', false)
*        // Prints 's is a string with 0123456789 numbers in it and two strings.'
*
* Warnings:
*        Since $start and $end both take either a string or an integer:
*            If the character or string you are searching $str for is a number, pass it as a quoted string.
*        If $end is (integer) 0, an empty string will be returned.
*        Since this function takes negative strings ('-search_string'):
*            If the string your using in $start or $end is a '-' or begins with a '-' escape it with a '\'.
*            This only applies to the *first* character of $start or $end.
*/

// Define stripos() if not defined (PHP < 5).
if (!is_callable("stripos")) {
    function
stripos($str, $needle, $offset = 0) {
        return
strpos(strtolower($str), strtolower($needle), $offset);
    }
}

function
substrpos($str, $start, $end = false, $ignore_case = false) {
   
// Use variable functions
   
if ($ignore_case === true) {
       
$strpos = 'stripos'; // stripos() is included above in case it's not defined (PHP < 5).
   
} else {
       
$strpos = 'strpos';
    }

   
// If end is false, set it to the length of $str
   
if ($end === false) {
       
$end = strlen($str);
    }

   
// If $start is a string do what's needed to make it an integer position for substr().
   
if (is_string($start)) {
       
// If $start begins with '-' start processing until there's no more matches and use the last one found.
       
if ($start{0} == '-') {
           
// Strip off the '-'
           
$start = substr($start, 1);
           
$found = false;
           
$pos = 0;
            while((
$curr_pos = $strpos($str, $start, $pos)) !== false) {
               
$found = true;
               
$pos = $curr_pos + 1;
            }
            if (
$found === false) {
               
$pos = false;
            } else {
               
$pos -= 1;
            }
        } else {
           
// If $start begins with '\-', strip off the '\'.
           
if ($start{0} . $start{1} == '\-') {
               
$start = substr($start, 1);
            }
           
$pos = $strpos($str, $start);
        }
       
$start = $pos !== false ? $pos : 0;
    }

   
// Chop the string from $start to strlen($str).
   
$str = substr($str, $start);

   
// If $end is a string, do exactly what was done to $start, above.
   
if (is_string($end)) {
        if (
$end{0} == '-') {
           
$end = substr($end, 1);
           
$found = false;
           
$pos = 0;
            while((
$curr_pos = strpos($str, $end, $pos)) !== false) {
               
$found = true;
               
$pos = $curr_pos + 1;
            }
            if (
$found === false) {
               
$pos = false;
            } else {
               
$pos -= 1;
            }
        } else {
            if (
$end{0} . $end{1} == '\-') {
               
$end = substr($end, 1);
            }
           
$pos = $strpos($str, $end);
        }
       
$end = $pos !== false ? $pos : strlen($str);
    }

   
// Since $str has already been chopped at $start, we can pass 0 as the new $start for substr()
   
return substr($str, 0, $end);
}

?>

I've used the between, after, before, etc functions that biohazard put together for years and they work great.  I've also added to it a new function that I use a lot and thought others might like it as well.  It uses his before/after functions so they are required to use it.

<?php
$example_html
= "<p>test1 Test2</p><title>hi there</title><p>Testing</p>";
$paragraph_text = multi_between('<p>', '</p>', $example_html);

//Prints an arry of:
//Array ( [1] => test1 Test2 [2] => Testing )
print_r($paragraph_text);

function
multi_between($this, $that, $inthat)
{
  
$counter = 0;
   while (
$inthat)
   {
     
$counter++;
     
$elements[$counter] = before($that, $inthat);
     
$elements[$counter] = after($this, $elements[$counter]);
     
$inthat = after($that, $inthat);
   }
   return
$elements;
}
//Get the help functions from biohazard's post below.
?>

II use my random password generator class

<?php
/*
  * Ali GOREN
  *
  *
*/

class SifreOlusturucu {

   
//var $boyut; test

   
function __construct($boyut = 8) { // 8 default, 14 or more good and recommended length
       
$this->boyut = $boyut;
    }

    function
sifreOlustur() {
       
//$this->boyut;
       
$karakterler = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?';
       
$sifre = substr( str_shuffle( $karakterler ), 0, $this->boyut);
       
print_r($sifre);
    }
}

$olustur = new SifreOlusturucu(16);
$olustur->sifreOlustur(); // output: wIsLiXzH1uP@hqSm

If you want to have a string BETWEEN two strings, just use this function:

<?php
function get_between($input, $start, $end)
{
 
$substr = substr($input, strlen($start)+strpos($input, $start), (strlen($input) - strpos($input, $end))*(-1));
  return
$substr;
}

//Example:

$string = "123456789";
$a = "12";
$b = "9";

echo
get_between($string, $a, $b);

//Output:
//345678
?>

Using substr() to examine characters of a string without altering the string.

<?php
$string
= 'This is my string';
$length = strlen($string);
$myChar = 'm';

for(
$i = 0; $i < $length; $i++) {

   
$showString_i = substr($string, $i, 1);
    if(
$myChar == $showString_i) return $i;
}
?>

can also examine subs.

<?php
//substring without words breaking

$str = "aa bb ccc ddd ee fff gg hhh iii";

echo
substr(($str=wordwrap($str,$,'$$')),0,strpos($str,'$$'));
?>

One thing to keep in mind when using string indexes and UTF-8 is that string indexes are NOT multi-byte safe.

<?php
$string
= 'äää1';
echo
$string[3];
?>

Outputs:
¤

When it logically should output "1". This is not a bug, as PHP 'normal' string functions are not intended to be multi-byte safe. This can be solved by using this function

<?php
/**
*
* @param string $string String to "search" from
* @param int $index Index of the letter we want.
* @return string The letter found on $index.
*/
function charAt($string, $index){
    if(
$index < mb_strlen($string)){
        return
mb_substr($string, $index, 1);
    }
    else{
        return -
1;
    }
}
?>

Shortens the filename and its expansion has seen.

<?php
$file
= "Hellothisfilehasmorethan30charactersandthisfayl.exe";

function
funclongwords($file)
{
if (
strlen($file) > 30)
{
$vartypesf = strrchr($file,".");
$vartypesf_len = strlen($vartypesf);
$word_l_w = substr($file,0,15);
$word_r_w = substr($file,-15);
$word_r_a = substr($word_r_w,0,-$vartypesf_len);

return
$word_l_w."...".$word_r_a.$vartypesf;
}
else
return
$file;
}
// RETURN: Hellothisfileha...andthisfayl.exe
?>

Substring utf-8 strings!
very simple!

<?php
function substru($str,$from,$len){
    return
preg_replace('#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'. $from .'}'.'((?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'. $len .'}).*#s','$1', $str);
}
?>

And as always there is bound to be a bug:

<?php
function strlen_entities($text)
{
   
preg_match_all(
       
'/((?:&(?:#[0-9]{2,}|[a-z]{2,});)|(?:[^&])|'.       
       
'(?:&(?!\w;)))s',$text,$textarray);
    return
count($textarray[0]);
}
function
substr_entities($text,$start,$limit=0)
{
   
$return = '';
   
preg_match_all(
       
'/((?:&(?:#[0-9]{2,}|[a-z]{2,});)|(?:[^&])|'.       
       
'(?:&(?!\w;)))s',$text,$textarray);
   
$textarray = $textarray[0];
   
$numchars = count($textarray)-1;
    if (
$start>=$numchars)
        return
false;
    if (
$start<0)
    {
       
$start = ($numchars)+$start+1;
    }
    if (
$start>=0)
    {
        if (
$limit==0)
        {
           
$end=$numchars;
        }
        elseif (
$limit>0)
        {
           
$end = $start+($limit-1);
        }
        else
        {
           
$end = ($numchars)+$limit;
        }

        for (
$i=$start;($i<=$end && isset($textarray[$i]));$i++)
        {
           
$return .= $textarray[$i];
        }
        return
$return;
    }
}
?>

I created some functions for entity-safe splitting+lengthcounting:

<?php
function strlen_entities($text)
{
   
preg_match_all(
       
'/((?:&(?:#[0-9]{2,}|[a-z]{2,});)|(?:[^&])|'.        
       
'(?:&(?!\w;)))s',$text,$textarray);
    return
count($textarray[0]);

function
substr_entities($text,$start,$limit=0)
{
   
$return = '';
   
preg_match_all(
       
'/((?:&(?:#[0-9]{2,}|[a-z]{2,});)|(?:[^&])|'.        
       
'(?:&(?!\w;)))s',$text,$textarray);
   
$textarray = $textarray[0];
   
$numchars = count($textarray)-1;
    if (
$start>=$numchars)
        return
false;
    if (
$start<0)
    {
       
$start = ($numchars)+$start+1;
    }
    if (
$start>=0)
    {
        if (
$limit==0)
        {
           
$end=$numchars;
        }
        elseif (
$limit>0)
        {
           
$end = $start+($limit-1);
        }
        else
        {
           
$end = ($numchars)+$limit;
        }

        for (
$i=$start;$i<=$end;$i++)
        {
           
$return .= $textarray[$i];
        }
        return
$return;
    }
}
?>

The javascript charAt equivalent in php of felipe has a little bug. It's necessary to compare the type (implicit) aswell or the function returns a wrong result:
<?php
function charAt($str,$pos) {
    return (
substr($str,$pos,1) !== false) ? substr($str,$pos,1) : -1;
}
?>

This returns the portion of str specified by the start and length parameters..
It can performs multi-byte safe on number of characters. like mb_strcut() ...

Note:
1.Use it like this bite_str(string str, int start, int length [,byte of on string]);
2.First character's position is 0. Second character position is 1, and so on...
3.$byte is one character length of your encoding, For example: utf-8 is "3", gb2312 and big5 is "2"...you can use the function strlen() get it...
Enjoy it :) ...

--- Bleakwind
QQ:940641
http://www.weaverdream.com

PS:I'm sorry my english is too poor... :(

<?php
// String intercept By Bleakwind
// utf-8:$byte=3 | gb2312:$byte=2 | big5:$byte=2
function bite_str($string, $start, $len, $byte=3)
{
   
$str     = "";
   
$count   = 0;
   
$str_len = strlen($string);
    for (
$i=0; $i<$str_len; $i++) {
        if ((
$count+1-$start)>$len) {
           
$str  .= "...";
            break;
        } elseif ((
ord(substr($string,$i,1)) <= 128) && ($count < $start)) {
           
$count++;
        } elseif ((
ord(substr($string,$i,1)) > 128) && ($count < $start)) {
           
$count = $count+2;
           
$i     = $i+$byte-1;
        } elseif ((
ord(substr($string,$i,1)) <= 128) && ($count >= $start)) {
           
$str  .= substr($string,$i,1);
           
$count++;
        } elseif ((
ord(substr($string,$i,1)) > 128) && ($count >= $start)) {
           
$str  .= substr($string,$i,$byte);
           
$count = $count+2;
           
$i     = $i+$byte-1;
        }
    }
    return
$str;
}

// Test
$str = "123456¶à×Ö½Ú123456×Ö·û´®123456½ØÈ¡º¯Êý";
for(
$i=0;$i<30;$i++){
    echo
"<br>".bite_str($str,$i,20);   
}
?>

<?php
/*
    An advanced substr but without breaking words in the middle.
    Comes in 3 flavours, one gets up to length chars as a maximum, the other with length chars as a minimum up to the next word, and the other considers removing final dots, commas and etcteteras for the sake of beauty (hahaha).
   This functions were posted by me some years ago, in the middle of the ages I had to use them in some corporations incorporated, with the luck to find them in some php not up to date mirrors. These mirrors are rarely being more not up to date till the end of the world... Well, may be am I the only person that finds usef not t bre word in th middl?

Than! (ks)

This is the calling syntax:

    snippet(phrase,[max length],[phrase tail])
    snippetgreedy(phrase,[max length before next space],[phrase tail])

*/

function snippet($text,$length=64,$tail="...") {
   
$text = trim($text);
   
$txtl = strlen($text);
    if(
$txtl > $length) {
        for(
$i=1;$text[$length-$i]!=" ";$i++) {
            if(
$i == $length) {
                return
substr($text,0,$length) . $tail;
            }
        }
       
$text = substr($text,0,$length-$i+1) . $tail;
    }
    return
$text;
}

// It behaves greedy, gets length characters ore goes for more

function snippetgreedy($text,$length=64,$tail="...") {
   
$text = trim($text);
    if(
strlen($text) > $length) {
        for(
$i=0;$text[$length+$i]!=" ";$i++) {
            if(!
$text[$length+$i]) {
                return
$text;
            }
        }
       
$text = substr($text,0,$length+$i) . $tail;
    }
    return
$text;
}

// The same as the snippet but removing latest low punctuation chars,
// if they exist (dots and commas). It performs a later suffixal trim of spaces

function snippetwop($text,$length=64,$tail="...") {
   
$text = trim($text);
   
$txtl = strlen($text);
    if(
$txtl > $length) {
        for(
$i=1;$text[$length-$i]!=" ";$i++) {
            if(
$i == $length) {
                return
substr($text,0,$length) . $tail;
            }
        }
        for(;
$text[$length-$i]=="," || $text[$length-$i]=="." || $text[$length-$i]==" ";$i++) {;}
       
$text = substr($text,0,$length-$i+1) . $tail;
    }
    return
$text;
}

/*
echo(snippet("this is not too long to run on the column on the left, perhaps, or perhaps yes, no idea") . "<br>");
echo(snippetwop("this is not too long to run on the column on the left, perhaps, or perhaps yes, no idea") . "<br>");
echo(snippetgreedy("this is not too long to run on the column on the left, perhaps, or perhaps yes, no idea"));
*/
?>

Here is also a nice (but a bit slow) alternative for colorizing an true color image:

<?php
// $colorize = hexadecimal code in String format, f.e. "10ffa2"
// $im = the image that have to be computed

$red = hexdec(substr($colorize, 0, 2));
$green = hexdec(substr($colorize, 2, 2));
$blue = hexdec(substr($colorize, 4, 2));

$lum_c = floor(($red*299 + $green*587 + $blue*144) / 1000);

for (
$i = 0; $i < $lum_c; $i++)
{
 
$r = $red * $i / $lum_c;
 
$g = $green * $i / $lum_c;
 
$b = $blue * $i / $lum_c;
 
$pal[$i] = $r<<16 | $g<<8 | $b;
}
$pal[$lum_c] = $red<<16 | $green<<8 | $blue;
for (
$i = $lum_c+1; $i < 255; $i++)
{
 
$r = $red + (255-$red) * ($i-$lum_c) / (255-$lum_c);
 
$g = $green + (255-$green) * ($i-$lum_c) / (255-$lum_c);
 
$b = $blue + (255-$blue) * ($i-$lum_c) / (255-$lum_c);
 
$pal[$i] = $r<<16 | $g<<8 | $b;
}

$sy = imagesy($im);
$sx = imagesx($im);
for(
$y=0;$y<$sy;$y++)
{
  for(
$x=0;$x<$sx;$x++)
  {
   
$rgba = imagecolorat($im, $x, $y);
   
$a = ($rgba & 0x7F000000) >> 24;
   
$r = ($rgba & 0xFF0000) >> 16;
   
$g = ($rgba & 0x00FF00) >> 8;
   
$b = ($rgba & 0x0000FF);

   
$lum = floor(($r*299+$g*587+$b*144)/1000);

   
imagesetpixel($im, $x, $y, $a<<24 | $pal[$lum]);
  }
}
?>

Here's a little addon to the html_substr function posted by fox.

Now it counts only chars outside of tags, and doesn't cut words.

Note: this will only work in xhtml strict/transitional due to the checking of "/>" tags and the requirement of quotations in every value of a tag. It's also only been tested with the presence of br, img, and a tags, but it should work with the presence of any tag.

<?php
function html_substr($posttext, $minimum_length = 200, $length_offset = 20, $cut_words = FALSE, $dots = TRUE) {
  
   
// $minimum_length:
    // The approximate length you want the concatenated text to be  


    // $length_offset:
    // The variation in how long the text can be in this example text
    // length will be between 200 and 200-20=180 characters and the
    // character where the last tag ends

    // Reset tag counter & quote checker
   
$tag_counter = 0;
   
$quotes_on = FALSE;
   
// Check if the text is too long
   
if (strlen($posttext) > $minimum_length) {
       
// Reset the tag_counter and pass through (part of) the entire text
       
$c = 0;
        for (
$i = 0; $i < strlen($posttext); $i++) {
           
// Load the current character and the next one
            // if the string has not arrived at the last character
           
$current_char = substr($posttext,$i,1);
            if (
$i < strlen($posttext) - 1) {
               
$next_char = substr($posttext,$i + 1,1);
            }
            else {
               
$next_char = "";
            }
           
// First check if quotes are on
           
if (!$quotes_on) {
               
// Check if it's a tag
                // On a "<" add 3 if it's an opening tag (like <a href...)
                // or add only 1 if it's an ending tag (like </a>)
               
if ($current_char == '<') {
                    if (
$next_char == '/') {
                       
$tag_counter += 1;
                    }
                    else {
                       
$tag_counter += 3;
                    }
                }
               
// Slash signifies an ending (like </a> or ... />)
                // substract 2
               
if ($current_char == '/' && $tag_counter <> 0) $tag_counter -= 2;
               
// On a ">" substract 1
               
if ($current_char == '>') $tag_counter -= 1;
               
// If quotes are encountered, start ignoring the tags
                // (for directory slashes)
               
if ($current_char == '"') $quotes_on = TRUE;
            }
            else {
               
// IF quotes are encountered again, turn it back off
               
if ($current_char == '"') $quotes_on = FALSE;
            }
          
           
// Count only the chars outside html tags
           
if($tag_counter == 2 || $tag_counter == 0){
               
$c++;
            }          
                          
           
// Check if the counter has reached the minimum length yet,
            // then wait for the tag_counter to become 0, and chop the string there
           
if ($c > $minimum_length - $length_offset && $tag_counter == 0 && ($next_char == ' ' || $cut_words == TRUE)) {
               
$posttext = substr($posttext,0,$i + 1);              
                if(
$dots){
                  
$posttext .= '...';
                }
                return
$posttext;
            }
        }
    }  
    return
$posttext;
}

?>

I needed to cut a string after x chars at a  html converted utf-8 text (for example Japanese text like &#23344;&#35632;&#24368;&#33072;&#27440;&#32591;).
The problem was, the different length of the signs, so I wrote the following function to handle that.
Perhaps it helps.

<?php

function html_cutstr ($str, $len)
{
    if (!
preg_match('/\&#[0-9]*;.*/i', $str))
    {
       
$rVal = strlen($str, $len);
        break;
    }

   
$chars = 0;
   
$start = 0;
    for(
$i=0; $i < strlen($str); $i++)
    {
        if (
$chars >= $len)
        break;

       
$str_tmp = substr($str, $start, $i-$start);
        if (
preg_match('/\&#[0-9]*;.*/i', $str_tmp))
        {
           
$chars++;
           
$start = $i;
        }
    }
   
$rVal = substr($str, 0, $start);
    if (
strlen($str) > $start)
   
$rVal .= " ...";
    return
$rVal;
}
?>