Re: Re: poll: howto do informative error handling without the fatalities

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux