Well, i've thought of a few ways to allow localized overriding of values returned by functions in case of an error. I have yet to figure out what the exact advantages are of this code-standard, but the overhead seems acceptable and i recon this, when done, will beat the "trigger_error()-try-catch" paradigm. I'd like to hear your comments. // imo unsafe & prone to fatalities: $r = funcA ( funcB ( funcC ($p) ), funcD ($q) ); // "safe"; make all notices, warnings and errors from any level // in the call-chain fully visible, identifiable, and "survivable/fudgeable" // by code at (all) higher levels in the call-chain. // [disclaimer] the code below here doesn't pass 3rd-level (funcC()) // (meta-)results back to the first level (funcA()) yet, but this code // is a start towards that; $r = funcA (defaults(array(0=>'[funcB failed]',1=>'funcD failed'))), funcB (defaults($onError_cCallvalue), funcC (defaults($onError_pValue), $p) ), funcD (defaults($onError_qValue), $q) ); function funcA ($defaults, $returnedByFuncB, $returnedByFuncD) { $returnedByFuncB = workWith ($defaults, $returnedByFuncB, 0); $returnedByFuncD = workWith ($defaults, $returnedByFuncD, 1); //all parameters (with idx>0) are meta-arrays containing the "parameter-value" and all meta-info. // workWith() always returns the actual parameter-value in $p['workValue']; //if any parameter $p (with idx>0) is not a meta-array, // workWith($d, $r, $n) turns it into a meta array( // 'workValue' => $p // ); //if a param is a meta-array $p, and it contains an ['errors'] subarray, // workWith() sets by-reference $p['workValue'] to one of these (order of trying): // $defaults['onError'][$n] (localized override) // $p['onErrorDefault'], (functions own default value for when an error occurs) //first call to workWith(,,0) will call beginErrorContext() //beginErrorContext() will increase a global idx $callID (int), // used to list all notices, warnings and errors, and their details in // the global variable $callsErrors[$callID][$errorIdx++] = array( // 'errorMsg' => 'for coders' // (optional:)'userErrorMsg' => 'for laymen' // 'backtrace' => array(....) // ) // the never-fatal error handler specified with set_error_handler() will // call getDebugInfo() and append full error info into // $callsErrors[$callID][$errorIdx++] //forwardDefaults() clones all meta-details for // re-used parameters into a new $defaults array to be used // by funcE(). //the 2nd parameter for forwardDefaults lists which parameter // passed deeper refers to which parameter received by this here function. //the 3rd parameter for forwardDefaults is used to specify new defaults. $returnedByFuncF = funcF('blablasetting'); $x = funcE ( forwardDefaults($defaults, array(0=>0,2=>1), array(1 => 'defaultblabla')), $returnedByFuncB, $returnedByFuncF, $returnedByFuncD ); return goodResult($x); } function funcE ($defaults, $returnedByFuncB, $returnedByFuncF, $returnedByFuncD) { $returnedByFuncB = workWith ($defaults, $returnedByFuncB, 0); $returnedByFuncF = workWith ($defaults, $returnedByFuncF, 2); $returnedByFuncD = workWith ($defaults, $returnedByFuncD, 2); // do a call that might raise E_WARNINGS or other crap; // safeCall() is only a try-except struct to call in this case // str_replace('xx','yy', ...) and if it fails, // return the default instead of the actual result. $x = safeCall ( defaults('returnedByFuncB not a string'), 'str_replace', 'xx','yy',$returnedByFuncB ); if (is_string($returnedByFuncB) && is_string($returnedByFuncD)) { return goodResult ( $returnedByFuncB . $returnedByFuncD . $x ); // goodResult() and badResult() will both call // endErrorContext(), and copy the errors in // $callsErrors[$callID] // to the array returned to the calling function. // goodResult() and badResult() will call processErrors(), // which is repsonsible for mailing / db-storage of any // notices, warnings, errors, etc. } else { // badResult() will call getDebugInfo() to include // a full trace, superglobals, lotsa details. return badResult (array( 'errorMsg' => 'params 1 and 2 must be strings' 'onErrorDefault' => '' )); //shorthand of the above: return badResult ('params 1 and 2 must be strings', ''); } } function defaults () { $r = array ( 'isMetaForFuncs' => true ); if (func_num_args()==1) { return array_merge_recursive ($r, array('onError'=>array(0=>func_get_arg(0)))); } else { switch (func_get_arg(0)) { case 'onError': $p = func_get_arg(1); if (is_array($p)) { return array_merge_recursive ($r, array('onError'=>$p)); } else { return array_merge_recursive ($r, array('onError'=>array(0=>$p))); } break; } } } I also considered the following constructs but rejected them for clumsiness (first) or sheer uselessness (2nd). $r = funcA ($bcalldef, funcB($ccalldef, funcC ($pdef, $p)), $dcalldef, funcD($qdef, $q)); $r = funcA ( funcB ( funcC ( $p ) ), funcD ($q), array ( 'isMetaForFuncs' => true, 0 => array ( 'onError' => $bCallDefaultOnError, 0 => array ( 'onError' => $cCallDefaultOnError, 0 => array ( 'onError' => $pDefaultOnError, ) ) ), 1 => array ( 'onError' => $qDefaultOnError ) ); -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php