starts_with, notice backtraces, better database error reporting and return values

feature/formhandler
Sven Slootweg 10 years ago
parent 37b404c2dd
commit 87a0cadb18

@ -102,6 +102,51 @@ if(!empty($cphp_config->autoloader))
spl_autoload_register('cphp_autoload_class');
}
/* https://stackoverflow.com/a/1159235/1332715 */
set_error_handler(function($errno, $errstr, $errfile, $errline, $errcontext) {
if(!(error_reporting() & $errno))
return;
switch($errno) {
case E_WARNING :
case E_USER_WARNING :
case E_STRICT :
case E_NOTICE :
case E_USER_NOTICE :
$type = 'warning';
$fatal = false;
break;
default :
$type = 'fatal error';
$fatal = true;
break;
}
$trace = array_reverse(debug_backtrace());
array_pop($trace);
if(php_sapi_name() == 'cli') {
echo 'Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline . ':' . "\n";
foreach($trace as $item)
echo ' ' . (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()' . "\n";
} else {
echo '<p class="error_backtrace">' . "\n";
echo ' Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline . ':' . "\n";
echo ' <ol>' . "\n";
foreach($trace as $item)
echo ' <li>' . (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()</li>' . "\n";
echo ' </ol>' . "\n";
echo '</p>' . "\n";
}
if(ini_get('log_errors')) {
$items = array();
foreach($trace as $item)
$items[] = (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()';
$message = 'Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline . ': ' . join(' | ', $items);
error_log($message);
}
if($fatal)
exit(1);
});
set_exception_handler(function($e){
/* Intentionally not using the templater here; any inner exceptions
* cause serious debugging issues. Avoiding potential issues by just

@ -29,6 +29,8 @@ class PrototypeException extends BaseException {}
class ConstructorException extends BaseException {}
class MissingDataException extends BaseException {}
class DatabaseException extends BaseException {}
class DatabaseDuplicateException extends DatabaseException {}
class DatabaseConstraintException extends DatabaseException {}
class TypeException extends BaseException {}
class DeprecatedException extends BaseException {}

@ -371,6 +371,11 @@ function generate_pagination($min, $max, $current, $around, $start, $end)
}
}
function starts_with($haystack, $needle)
{
return (substr($haystack, 0, strlen($needle)) == $needle);
}
function ends_with($haystack, $needle)
{
return (substr($haystack, -strlen($needle)) == $needle);

@ -88,19 +88,44 @@ class CachedPDO extends PDO
}
}
else
{
$last_id = $this->lastInsertId();
if($last_id == "0" || !starts_with(strtoupper($query), "INSERT"))
{
/* There were zero results. Return null instead of an object without results, to allow for statements
* of the form if($result = $database->CachedQuery()) . */
return null;
}
else
{
/* This was an INSERT query. Return the primary ID of the created row. */
return $last_id;
}
}
}
else
{
/* The query failed. */
$err = $statement->errorInfo();
if($err[0] == "23000")
{
if(starts_with($err[2], "Duplicate entry")) /* There does not seem to be a better way of doing this. */
{
throw new DatabaseDuplicateException("The query failed because one of the keys was not unique: {$err[2]}", 0, null, array('query' => $query, 'parameters' => $parameters));
}
else
{
throw new DatabaseConstraintException("The query violates a database constraint: {$err[2]}", 0, null, array('query' => $query, 'parameters' => $parameters));
}
}
else
{
throw new DatabaseException("The query failed: {$err[2]}", 0, null, array('query' => $query, 'parameters' => $parameters));
}
}
}
return $return_object;
}

Loading…
Cancel
Save