get error throwing php script name inside class - php

I am using Bennett Stone php wrapper class for mysqli operations. class is working fine without any issues. There is a function inside it (shared below) which sends an email to administrator for any kind of mysqli errors.
Issue
There are 100's of scripts using this class, I am not able to find out which script thrown any particular error.
What i want
I want to get the full path of error originating script inside class from where query originated. for example, test.php contains query & post execution if any error comes out then i want complete path of test.php inside error handling function along with error details (shared below).
What i can do
Class modification I can do by my own
I am getting details like this:
Error at 2016-08-23 05:44:18:
Query: SELECT email FROM users WHERE
Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
Error handling function
public function log_db_errors( $error, $query )
{
$message = '<p>Error at '. date('Y-m-d H:i:s').':</p>';
$message .= '<p>Query: '. htmlentities( $query ).'<br />';
$message .= 'Error: ' . $error;
$message .= '</p>';
if( defined( 'SEND_ERRORS_TO' ) )
{
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'To: Admin <'.SEND_ERRORS_TO.'>' . "\r\n";
$headers .= 'From: systems<noreply#'.$_SERVER['SERVER_NAME'].'.com>' . "\r\n";
mail( SEND_ERRORS_TO, 'Database Error', $message, $headers );
}
else
{
trigger_error( $message );
}
if( !defined( 'DISPLAY_DEBUG' ) || ( defined( 'DISPLAY_DEBUG' ) && DISPLAY_DEBUG ) )
{
echo $message;
}
}

Put these lines somewhere above all your codes:
ini_set('display_errors', 0);
ini_set('log_errors', 1);
error_reporting(E_ALL);
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
and you will have every error logged with a stack trace. While all this bushy "log_db_errors" stuff will be thrown away.
the problem solved.
NB. This wrapper class is just terrible. Utilizes almost every bad practice ever exists.

What you can do is catching exception and edit error message, using some magic php const in it : PHP: Magic constants
Example, in your class, around the query :
try {
// your query
} catch (Exception $e) {
// launch your log_db_errors() function, with some of const, like __CLASS__, __LINE__, etc :
$error = '[' . __FILE__ . '][' . __CLASS__ . '::' . __FUNCTION__ . '][' . __LINE__ . '] : ' . $e->getMessage();
// ...
}

Related

What is the scope of error_get_last() in PHP?

I've been using error_get_last() in combination with register_shutdown_function() to create an error report for some of my scripts. It's been working fine for the most part.
Every now and then, though, the error report will show an error from a different script.
I'm not quite sure how that can happen. Can anyone explain?
I'm wondering if error_get_last() in one script should be able to show errors from different scripts and if that's the case, under what circumstances would that happen?
My only guess is that the error is saved for a short time so that a script that finishes execution at almost the same time might catch another script's errors. Could that be it?
This is the code I use and have included in many different PHP files:
function send_error_report($extra) {
global $conn;
$base_url = ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']=='on' ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'];
$url = $base_url . $_SERVER["REQUEST_URI"];
$error = error_get_last();
if (isset($error)) {
$error_str = "Type: " . $error['type'] . " | Message: " . $error['message'] . " | File: " . $error['file'] . " | Line: " . $error['line'];
$sql = "INSERT INTO `error_report` (`script`, `error`) VALUES ('$url', '" . $error_str . " - " . $extra . "');";
$conn->query($sql);
}
}
register_shutdown_function('send_error_report', '');

file_get_contents will not output in my error handler script

I have a strange problem with regards to a custom error handler function that deals with fatal errors. The error on my website is an "Fatal error: Allowed memory size of 134217728 bytes exhausted" - which of course I will fix. But I want a custom error page to show if it happens again.
The following code echo's number 1, but not my "error-page.php" and does not echo number 2. So it feels like the script is erroring on the file_get_contents line - but it's not telling me why.
To make matters worse - it echo's fine on my development server! But I cannot think of a set up difference that would effect this.
To try and solve this I have echo'd out the full path for the file_get_contents and it is correct - and file_exists returns true - so I am utterly stumped!
Worth noting - error-page.php is just a static HTML page so no offending code in that! It won't even file_get_contents a test.txt.
error_reporting(-1);
set_error_handler("customErrorPage");
register_shutdown_function('shutdownFunction');
function shutdownFunction()
{
$last_error = error_get_last();
if ($last_error['type'] === E_ERROR) {
fatalErrorHandler(E_ERROR, $last_error['message'], $last_error['file'], $last_error['line'], "");
}
}
function fatalErrorHandler($error_level,$error_message,$error_file,$error_line,$error_context) {
http_response_code(500);
$errorEmail = "<strong>Error on page:</strong> http://" . $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"] . "<br />\n";
$errorEmail .= "<strong>Message:</strong> " . $error_message . "<br />\n";
$errorEmail .= "<strong>IP:</strong> " . getRealIpAddr() . "<br />\n";
$errorEmail .= "<strong>Line:</strong> " . $error_line . "<br />\n";
$errorEmail .= "<strong>File:</strong> " . $error_file . "<br />\n";
if ((strpos($_SERVER['SERVER_NAME'], ".com") > 0)) {
$to = "james#email.com";
$subject = "FATAL Error on " . $_SERVER["SERVER_NAME"] . " - " . $error_message;
$headers = "MIME-Version: 1.0'" . "\r\n";
$headers .= "Content-type: text/html; charset=iso-8859-1". "\r\n";
$headers .= "From: " . WEBSITE_COMPANY . " <errors#" . WEBSITE_DOMAIN . ">" . "\r\n";
mail($to, $subject, $errorEmail, $headers);
echo "1";
echo file_get_contents($_SERVER["DOCUMENT_ROOT"] . "includes/error-page.php");
echo "2";
die;
} else {
echo $errorEmail;
die;
}
}
This is what I see on my screen when running the script:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried
to allocate 14907 bytes) in
/home/sure-wise/htdocs/objects/myaccount.php on line 2666 1

Yii2 in Third Party systems for ActiveRecord. How to deal with exceptions

I use Yii2 with my framework because I like ActiveRecord and QueryBuilder.
Yii2 Official docs
describes how to use it.
It works, but Yii2 takes all control of PHP exceptions and warnings in ErrorHandler.php
/**
* Register this error handler
*/
public function register()
{
ini_set('display_errors', false);
set_exception_handler([$this, 'handleException']);
if (defined('HHVM_VERSION')) {
set_error_handler([$this, 'handleHhvmError']);
} else {
set_error_handler([$this, 'handleError']);
}
if ($this->memoryReserveSize > 0) {
$this->_memoryReserve = str_repeat('x', $this->memoryReserveSize);
}
register_shutdown_function([$this, 'handleFatalError']);
}
I don't know how to deal with it.
For example, I have DBException form Yii. If I set my own set_exception_handler, it will have very poor information about exception: only code and message. It will be very difficult to debug it without prepared query, query parameters, etc.
If I use Yii2's exception handler - I have to rewrite all my framework with Yii2 exceptions. Thats not good and I don't really like Yii2 letters and exception templates. All I need from Yii2 is work with DB.
Do you have any ideas how can I solve this situation?
I realized, that Yii's Database Exception has all information about request and error. Also that Exception has some additional methods for another info. Thats enough to controll all Exceptions and errors by my Framework as usual.
So I rewrited all handlers again to my handlers
spl_autoload_register(array("MyClass", 'autoload'));
set_exception_handler(['MyClass','exceptionHandler']);
set_error_handler(['MyClass','errorHandler']);
and collect all usefull information to error body
$body .= "Error: " . $e->getMessage() . PHP_EOL;
$body .= "File: " . $e->getFile() . ":" . $e->getLine() . PHP_EOL;
$body .= "Trace:" .$e->getTraceAsString() . PHP_EOL;
$prev = $e->getPrevious();
if ($prev) {
$body .= "Next To: ";
$body .= get_class($prev)." ".PHP_EOL;
$body .= $prev->getMessage();
}
if ($e instanceof yii\db\Exception) {
$body .= "Additional Info: " . (print_r($e->errorInfo, true));
}

How to debug php code in this case?

I 'm developing an android app which connects to database using PHP API. It's the first time for me to encounter PHP.
What happens is that I "POST" parameters to the php code with a URL to connect to it then php makes a query to my database and store them ... the issue is that all I see is what happens in logcat, I have no idea what is goin on with the PHP so if there is something wrong in there what can I do to debug it ?
Note : I 'm already familiar with echos and var dump I 'm looking for fully debugging tool that will allow me to debug the script without actually running it directly and by that I mean accessing it from my android project.
In such cases i log / append all actions on php side into a file - with a simple
file_put_contents({file}, {data}, FILE_APPEND);
.
u could also catch nearly every error in php with following methods:
set_error_handler({YOUR_ERROR_HANDLER}, E_ALL);
register_shutdown_function({YOUR_ERROR_HANDLER});
http://php.net/manual/de/function.set-error-handler.php
http://php.net/manual/de/function.register-shutdown-function.php
example code of how would i test an envoirement in php, which i could not debug direct:
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
// will be triggered on every php shutdown - will log the last error (if one occurs)
register_shutdown_function(function()
{
// get last error
$aError = error_get_last();
if(!empty($aError))
{
logAction('called from register_shutdown_function | ' . $aError['message']);
}
});
// will be triggered on every error
set_error_handler(function($iErrCode, $sErrorText, $sErrorFile = '', $sErrorLine = '')
{
logAction('called from set_error_handler | Code: ' . $iErrCode . ' Text: ' . $sErrorText . ' File: ' . $sErrorFile . ' Line: ' . $sErrorLine);
}, E_ALL);
// will be triggered on every exception
set_exception_handler(function(\Exception $e)
{
logAction('called from set_exception_handler | Code: ' . $e->getCode() . ' Text: ' . $e->getMessage() . ' File: ' . $e->getFile() . ' Line: ' . $e->getLine());
});
// main log / debug method
function logAction($sText)
{
$sDate = date('Y.m.d H:i:s');
file_put_contents('debug.log', $sDate . ': ' . $sText, FILE_APPEND);
}

PHP Does Custom Exception Handler require try {} catch?

I've written the following custom Exception handler:
namespace System\Exception;
class Handler extends \Exception {
public static function getException($e = null) {
if (ENVIRONMENT === 0 && is_object($e)) {
$message = "<p>";
$message .= "Exception: " . $e->getMessage();
$message .= "<br />File: " . $e->getFile();
$message .= "<br />Line: " . $e->getLine();
$message .= "<br />Trace: " . $e->getTrace();
$message .= "<br />Trace as string: " . $e->getTraceAsString();
$message .= "</p>";
} else {
$message = '<h1>Exception</h1>';
$message .= '<p>There was a problem.</p>';
}
#require_once('header.php');
echo $message;
#require_once('footer.php');
exit();
}
public static function getError($errno = 0, $errstr = null, $errfile = null, $errline = 0) {
if (ENVIRONMENT === 0) {
$message = "<p>";
$message .= "Error: " . $errstr;
$message .= "<br />File: " . $errfile;
$message .= "<br />Line: " . $errline;
$message .= "<br />Number: " . $errno;
$message .= "</p>";
} else {
$message = '<h1>Error</h1>';
$message .= '<p>There was a problem.</p>';
}
#require_once('header.php');
echo $message;
#require_once('footer.php');
exit();
}
public static function getShutdown() {
$last_error = error_get_last();
if ($last_error['type'] === E_ERROR) {
self::getError(E_ERROR, $last_error['message'], $last_error['file'], $last_error['line']);
}
}
}
and have indicated that I want to use this class and its methods for processing all exceptions and errors generated by the system in the following way:
set_exception_handler(array("System\Exception\Handler", "getException"));
set_error_handler(array("System\Exception\Handler", "getError"), -1 & ~E_NOTICE & ~E_USER_NOTICE);
register_shutdown_function(array("System\Exception\Handler", "getShutdown"));
I have also indicated that I don't want errors to be displayed on the screen and wand to report all of the errors:
ini_set('display_errors', 'Off');
error_reporting(-1);
My question now is - do I still need to use the try { } catch () { } statement in order to catch any exceptions and errors? I know that the above is most probably not a bullet proof, but seem to be working so far without any try / catch statement by processing all uncaught exceptions and errors.
Also - is there any disadvantage by using custom exception handler and letting it catch all uncaught exceptions rather than doing this via try {} catch (i.e. performance / security etc.)?
You don't have to, but you cannot recover - using try/catch gives you the advantage of reacting to particular exception (for example file not found in some_custom_session_handling() might be a good place to use try/catch and log out such user without session file).
So the advantage is that you have prettier messages. The downside is that you treat exceptions always the same. It's not bad in itself, and should not degradate performance or security, but it misses the point of using exceptions in the first place.
However, it does not exclude using try/catch where you might want them, so I'd say it's a good failover solution, but should be avoided as a try/catch replacement
As jderda said, be using your aproach you are missing the point of exceptions: to check for any errors in the upper levels of your code and react to them - halt or treat the exception and move on. Your aproach is fine when you want to, for example, log all uncaught exceptions

Categories