3v4l.org

run code in 150+ php & hhvm versions
Bugs & Features
<?php header("content-type: text/plain"); error_reporting(E_ALL); $var='derp global $var...'; function hhb_var_dump() { //<changelog> //v5, fixed warnings on PHP < 5.0.2 (PHP_EOL not defined) (although we do not undefine("PHP_EOL") .. not sure how to do that :( ), //also we can use xdebug_var_dump when available now. //v4, now (tries to) tell you the source code that lead to the variables //v3, HHB_VAR_DUMP_START and HHB_VAR_DUMP_END . //v2, now compat with.. PHP5.0 + i think? tested down to 5.2.17 (previously only 5.4.0+ worked) //</changelog> //<settings> if(!defined('PHP_EOL')){//for PHP <5.0.2 $we_defined_PHP_EOL=true; define('PHP_EOL',"\n"); } $debug_hhb_var_dump = true; //if true, may throw exceptions on errors.. $use_xdebug_var_dump=false;//try to use xdebug_var_dump (instead of var_dump) if available? $fancy_sourcecode_analyze_setting = true; //false to disable the fancy source code analyze stuff. //(it will fallback to making $fancy_sourcecode_analyze_setting=false, if it fail to analyze the code, anyway..) $hhb_var_dump_prepend = 'HHB_VAR_DUMP_START'.PHP_EOL; $hhb_var_dump_append = 'HHB_VAR_DUMP_END'.PHP_EOL; //</settings> $use_xdebug_var_dump=($use_xdebug_var_dump && is_callable("xdebug_var_dump")); if(!defined("PHP_EOL")){//for PHP 5.0.2<=... $we_defined_PHP_EOL=true; define('PHP_EOL',"\n"); } $argv = func_get_args(); $argc = count($argv, COUNT_NORMAL); if (version_compare(PHP_VERSION, '5.4.0', '>=')) { $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); } else if (version_compare(PHP_VERSION, '5.3.6', '>=')) { $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); } else if (version_compare(PHP_VERSION, '5.2.5', '>=')) { $bt = debug_backtrace(false); } else { $bt = debug_backtrace(); }; $fancy_sourcecode_analyze = $fancy_sourcecode_analyze_setting; //later, $fancy_sourecode_analyze will be compared with $fancy_sourcecode_analyze_settings //to determine if the reason was an error analyzing, or if it was disabled.. $bt = $bt[0]; //<analyzeSourceCode> if ($fancy_sourcecode_analyze) { $argvSourceCode = array(0 => 'ignore [0]...'); try { if (version_compare(PHP_VERSION, '5.2.2', '<')) { throw new Exception("PHP version is <5.2.2 .. see token_get_all changelog.."); }; $xsource = file_get_contents($bt['file']); if (empty($xsource)) { throw new Exception('cant get the source of '.$bt['file']); }; $xsource.= '<?php ignore_this_hhb_var_dump_workaround();'; //workaround, making sure that at least 1 token is an array, and has the $tok[2] >= line of hhb_var_dump $xTokenArray = token_get_all($xsource); //<trim$xTokenArray> $tmpstr=''; $tmpUnsetKeyArray = array(); ForEach($xTokenArray as $xKey => $xToken) { if (is_array($xToken)) { $tmpstr = trim($xToken[1]); if (empty($tmpstr) && $tmpstr!=='0'/*string("0") is considered "empty" -.-*/) { $tmpUnsetKeyArray[] = $xKey; continue; }; switch ($xToken[0]) { case T_COMMENT: case T_DOC_COMMENT: //T_ML_COMMENT in PHP4 -.- case T_INLINE_HTML: { $tmpUnsetKeyArray[] = $xKey; continue; }; default: { continue; } } } else if (is_string($xToken)) { $tmpstr = trim($xToken); if (empty($tmpstr) && $tmpstr!=='0'/*string("0") is considered "empty" -.-*/) { $tmpUnsetKeyArray[] = $xKey; }; continue; } else { //should be unreachable.. //failed both is_array() and is_string() ??? throw new LogicException('Impossible! $xToken fails both is_array() and is_string() !! .. '); }; }; ForEach($tmpUnsetKeyArray as $toUnset) { unset($xTokenArray[$toUnset]); }; $xTokenArray = array_values($xTokenArray); //fixing the keys.. //die(var_dump('die(var_dump(...)) in '.__FILE__.':'.__LINE__,'before:',count(token_get_all($xsource),COUNT_NORMAL),'after',count($xTokenArray,COUNT_NORMAL))); unset($tmpstr,$xKey, $xToken, $toUnset, $tmpUnsetKeyArray); //</trim$xTokenArray> $firstInterestingLineTokenKey = -1; $lastInterestingLineTokenKey = -1; //<find$lastInterestingLineTokenKey> ForEach($xTokenArray as $xKey => $xToken) { if (!is_array($xToken) || !is_integer($xToken[2]) || $xToken[2] < $bt['line']) continue; //die(var_dump('die(var_dump(...)) in '.__FILE__.':'.__LINE__,$xToken,token_name($xToken[0]),$xTokenArray)); $tmpkey = $xKey; //we don't got what we want yet.. while (true) { if (!array_key_exists($tmpkey, $xTokenArray)) { throw new Exception('1unable to find $lastInterestingLineTokenKey !'); }; if ($xTokenArray[$tmpkey] === ';') { //var_dump(__LINE__.":SUCCESS WITH",$tmpkey,$xTokenArray[$tmpkey]); $lastInterestingLineTokenKey = $tmpkey; break; } //var_dump(__LINE__.":FAIL WITH ",$tmpkey,$xTokenArray[$tmpkey]); //if $xTokenArray has >=PHP_INT_MAX keys, we don't want an infinite loop, do we? ;p //i wonder how much memory that would require though.. over-engineering, err, time-wasting, ftw? if ($tmpkey >= PHP_INT_MAX) { throw new Exception('2unable to find $lastIntperestingLineTokenKey ! (PHP_INT_MAX reached without finding ";"...)'); }; ++$tmpkey; } break; }; if ($lastInterestingLineTokenKey <= -1) { throw new Exception('3unable to find $lastInterestingLineTokenKey !'); }; unset($xKey,$xToken,$tmpkey); //</find$lastInterestingLineTokenKey> //<find$firstInterestingLineTokenKey> //now work ourselves backwards from $lastInterestingLineTokenKey to the first token where $xTokenArray[$tmpi][1] == "hhb_var_dump" //i doubt this is fool-proof but.. cant think of a better way (in userland, anyway) atm.. $tmpi = $lastInterestingLineTokenKey; do { if (array_key_exists($tmpi, $xTokenArray) && is_array($xTokenArray[$tmpi]) && array_key_exists(1, $xTokenArray[$tmpi]) && is_string($xTokenArray[$tmpi][1]) && strcasecmp($xTokenArray[$tmpi][1], $bt['function']) === 0) { //var_dump(__LINE__."SUCCESS WITH",$tmpi,$xTokenArray[$tmpi]); if (!array_key_exists($tmpi + 2, $xTokenArray)) { //+2 because [0] is (or should be) "hhb_var_dump" and [1] is (or should be) "(" throw new Exception('1unable to find the $firstInterestingLineTokenKey...'); }; $firstInterestingLineTokenKey = $tmpi + 2; break; /**/ }; //var_dump(__LINE__."FAIL WITH ",$tmpi,$xTokenArray[$tmpi]); --$tmpi; } while (-1 < $tmpi); //die(var_dump('die(var_dump(...)) in '.__FILE__.':'.__LINE__,$tmpi)); if ($firstInterestingLineTokenKey <= -1) { throw new Exception('2unable to find the $firstInterestingLineTokenKey...'); }; unset($tmpi); //Note: $lastInterestingLineTokeyKey is likely to contain more stuff than only the stuff we want.. //</find$firstInterestingLineTokenKey> //<rebuildInterestingSourceCode> //ok, now we have $firstInterestingLineTokenKey and $lastInterestingLineTokenKey.... $interestingTokensArray = array_slice($xTokenArray, $firstInterestingLineTokenKey, (($lastInterestingLineTokenKey - $firstInterestingLineTokenKey) + 1)); unset($addUntil, $tmpi, $tmpstr,$tmpi,$argvsourcestr, $tmpkey,$xTokenKey,$xToken); $addUntil = array(); $tmpi = 0; $tmpstr = ""; $tmpkey = ""; $argvsourcestr = ""; //$argvSourceCode[X]='source code..'; ForEach($interestingTokensArray as $xTokenKey => $xToken) { if (is_array($xToken)) { $tmpstr = $xToken[1]; //var_dump($xToken[1]); } else if (is_string($xToken)) { $tmpstr = $xToken; //var_dump($xToken); } else { /*should never reach this */ throw new LogicException('Impossible situation? $xToken fails is_array() and fails is_string() ...'); }; $argvsourcestr.= $tmpstr; if ($xToken === '(') { $addUntil[] = ')'; continue; }; if ($xToken === ')') { if (false === ($tmpkey = array_search(')', $addUntil, false))) { $argvSourceCode[] = substr($argvsourcestr, 0, -1); //-1 is to strip the ")" if (count($argvSourceCode, COUNT_NORMAL) - 1 === $argc) /*-1 because $argvSourceCode[0] is bullshit*/ { break; /*We read em all! :D (.. i hope)*/ }; /*else... oh crap*/ throw new Exception('failed to read source code of (what i think is) argv['.count($argvSourceCode, COUNT_NORMAL).'] ! sorry..'); } unset($addUntil[$tmpkey]); continue; } if (empty($addUntil) && $xToken === ',') { $argvSourceCode[] = substr($argvsourcestr, 0, -1); //-1 is to strip the comma $argvsourcestr = ""; }; }; //die(var_dump('die(var_dump(...)) in '.__FILE__.':'.__LINE__, //$firstInterestingLineTokenKey,$lastInterestingLineTokenKey,$interestingTokensArray,$tmpstr //$argvSourceCode)); if (count($argvSourceCode, COUNT_NORMAL) - 1 != $argc) /*-1 because $argvSourceCode[0] is bullshit*/ { throw new Exception('failed to read source code of all the arguments! (and idk which ones i missed)! sorry..'); }; //</rebuildInterestingSourceCode> } catch (Exception $ex) { $argvSourceCode = array(); //clear it //TODO: failed to read source code //die("TODO N STUFF..".__FILE__.__LINE__); $fancy_sourcecode_analyze = false; //ERROR.. if ($debug_hhb_var_dump) { throw $ex; } else {/*exception ignored, continue as normal without $fancy_sourcecode_analyze */}; } unset($xsource, $xToken, $xTokenArray, $firstInterestingLineTokenKey, $lastInterestingLineTokenKey, $xTokenKey, $tmpi, $tmpkey); }; //</analyzeSourceCode> $msg = $hhb_var_dump_prepend; if ($fancy_sourcecode_analyze != $fancy_sourcecode_analyze_setting) { $msg.= ' (PS: some error analyzing source code)'.PHP_EOL; }; $msg.= 'in "'.$bt['file']. '": on line "'.$bt['line']. '": '.$argc. ' variable'.($argc === 1 ? '' : 's') //because over-engineering ftw? .PHP_EOL; if ($fancy_sourcecode_analyze) { $msg.= ' hhb_var_dump('; $msg.= implode(",", array_slice($argvSourceCode, 1));//$argvSourceCode[0] is bullshit. $msg.= ')'.PHP_EOL; } //array_unshift($bt,$msg); echo $msg; $i = 0; foreach($argv as &$val) { echo 'argv['.++$i.']'; if ($fancy_sourcecode_analyze) { echo ' >>>'.$argvSourceCode[$i].'<<<'; } echo ':'; if ($use_xdebug_var_dump) { xdebug_var_dump($val); } else { var_dump($val); }; } echo $hhb_var_dump_append; //call_user_func_array("var_dump",$args); } function shutdownf(){ global $starttime; //echo 'time used: ',microtime(true)-$starttime; } function f(){ return 'f() returns lol n stuff :D'; } register_shutdown_function("shutdownf"); $starttime=microtime(true); hhb_var_dump ( $var,'lol',array(array(array('',100)),NULL),"",f('', 'break(break me!!) break me!', 100, NULL ,array(array( '',100)) ),NULL,"",1337, 0 , (1?true:false) ,(1) && true );
Output for 7.0.0 - 7.1.0
HHB_VAR_DUMP_START in "/in/cBDKL": on line "286": 11 variables hhb_var_dump($var,'lol',array(array(array('',100)),NULL),"",f('','break(break me!!) break me!',100,NULL,array(array('',100))),NULL,"",1337,0,(1?true:false),(1)&&true) argv[1] >>>$var<<<:string(19) "derp global $var..." argv[2] >>>'lol'<<<:string(3) "lol" argv[3] >>>array(array(array('',100)),NULL)<<<:array(2) { [0]=> array(1) { [0]=> array(2) { [0]=> string(0) "" [1]=> int(100) } } [1]=> NULL } argv[4] >>>""<<<:string(0) "" argv[5] >>>f('','break(break me!!) break me!',100,NULL,array(array('',100)))<<<:string(26) "f() returns lol n stuff :D" argv[6] >>>NULL<<<:NULL argv[7] >>>""<<<:string(0) "" argv[8] >>>1337<<<:int(1337) argv[9] >>>0<<<:int(0) argv[10] >>>(1?true:false)<<<:bool(true) argv[11] >>>(1)&&true<<<:bool(true) HHB_VAR_DUMP_END
Output for 5.3.0 - 5.6.28, hhvm-3.10.0 - 3.12.0
HHB_VAR_DUMP_START in "/in/cBDKL": on line "287": 11 variables hhb_var_dump($var,'lol',array(array(array('',100)),NULL),"",f('','break(break me!!) break me!',100,NULL,array(array('',100))),NULL,"",1337,0,(1?true:false),(1)&&true) argv[1] >>>$var<<<:string(19) "derp global $var..." argv[2] >>>'lol'<<<:string(3) "lol" argv[3] >>>array(array(array('',100)),NULL)<<<:array(2) { [0]=> array(1) { [0]=> array(2) { [0]=> string(0) "" [1]=> int(100) } } [1]=> NULL } argv[4] >>>""<<<:string(0) "" argv[5] >>>f('','break(break me!!) break me!',100,NULL,array(array('',100)))<<<:string(26) "f() returns lol n stuff :D" argv[6] >>>NULL<<<:NULL argv[7] >>>""<<<:string(0) "" argv[8] >>>1337<<<:int(1337) argv[9] >>>0<<<:int(0) argv[10] >>>(1?true:false)<<<:bool(true) argv[11] >>>(1)&&true<<<:bool(true) HHB_VAR_DUMP_END