Simple string-split by root and sufix algorithm
About "best thing"... The "principle of simplest is best"  seems valid. The number of commands, and the computational simplicity of each command.


str_splitByRoot1: 2 fast commands (strpos and substr) and 1 condition and strlen
str_splitByRoot2: 2 fast commands (substr) and 1 to be checked (strspn+str ^ str)
str_splitByRoot2 optimized: 1 fast command (substr), 1 to be checked (strspn) and 1 condition.
...


So, my doubt was about strspn+str ^ str performance... And its time  struck me most,  was near time for str_splitByRoot1...

  $str_splitByRoot = array(
       function  ($str, $root){  // str_splitByRoot1()
            if (strpos($str,$root)===0)
                return array($root, substr($str, strlen($root)) );
           else 
                   return array( '', $str );
       },

       function  ($str, $root){ //str_splitByRoot2()
           $rootLen = strspn($str ^ $root, "\0");
           return array( substr($root,0,$rootLen), substr($str,$rootLen) );
       },
       function  ($str, $root){ //str_splitByRoot2() optimized
           $rootLen = strspn($str ^ $root, "\0");
           return array( $rootLen?$root:'' , substr($str,$rootLen) );
       },

       function  ($str, $root){  //str_splitByRoot3()
         $s = explode($root,$str);
         return ( count($s)&gt;1  &amp;&amp; !array_shift($s) )? 
             array($root,join($root,$s)): 
             array('',$str);
       }   

       function ($str, $root){ // str_splitByRoot5
            $root2 = str_replace(array('/','.','-'),array('\\/','\\.','\\-'),$root);
           if (preg_match("/^$root2(.+)$/",$str,$m))
                 return array($root,$m[1]);
           else 
                 return array('',$str);
       }
  );


  function str_sepByRoot($i,$str,$root){
       global $str_splitByRoot;
       global $debug;
            $func = $str_splitByRoot[$i];
            $s = join(' * ', call_user_func($str_splitByRoot[$i],$str,$root)); // $func($str,$root));
            if ($s &amp;&amp;  $debug)
                 print "\n ___ $s";
  }

  $debug=0;
  for ($i=0; $i&lt;count($str_splitByRoot); $i++) {
       print "\n--- $i ---";
       $time = microtime(true); // time in Microseconds
       for($j=0;($j&lt;333 &amp;&amp; !$debug) || ($debug &amp;&amp; $j&lt;1); $j++){
            str_sepByRoot($i,"walking","walk");
            str_sepByRoot($i,"hello","walk");
            str_sepByRoot($i,"walking-walk-walk","walk");
            str_sepByRoot($i,"/var/www/myApp","/var/www/");
            str_sepByRoot($i,"DOI:10.1038/ncomms7368","DOI:10.1038/ncomms");     
       }
       echo "\n", (microtime(true) - $time) . ' elapsed';
  }


Result:
--- 0 ---
0.0037140846252441 elapsed
--- 1 ---
0.0045409202575684 elapsed
--- 2 ---
0.0040040016174316 elapsed
--- 3 ---
0.0088369846343994 elapsed
--- 4 ---
0.0075829029083252 elapsed
--- 5 ---
0.0037930011749268 elapsed


Conclusion, using str_splitByRoot1 as reference (100%), 


str_splitByRoot2 optimized  is ~105% , so for practical use it's as good as  str_splitByRoot1.
str_splitByRoot2  is ~115%, something good when compared with str_splitByRoot3 (~125%).
str_splitByRoot5 is 225%... as expected, the worst (even without  str_replace regex escapes).




... But, the performance changes (!) when using a big root, an Lorem ipsum of 800 words. The performance profile changed to:


str_splitByRoot2 (optimized or not)  ~244%... bad!
str_splitByRoot3  (with direct split by explode) is ~120%, very good!
str_splitByRoot5 (regex)  ~390%, the worst of course.


So, the only that shows more "stability" (~120%)  about root length was str_splitByRoot5, and str_splitByRoot2 is not a good replacement for  str_splitByRoot1 in the context of big roots.