I'm building a MVC PHP framework. I'm working on error logging. I'm testing a system to show and log (in a .txt file) errors thrown by a try, catch block. Since it's short, I've included the whole of index.php:
<?php
// *** SETUP THE DOCUMENT ***
// Declare strict_types.
declare(strict_types = 1);
// Include the autoload file.
require_once "classes/autoload.php";
// Create a new config variable to allow us to call the config file from anywhere.
new Config();
// Setup error reporting according to the config.
error_reporting(Config::$config['defaults']['errReporting']);
ini_set("display_errors", Config::$config['defaults']['ini_setErrors']);
// Errors::showCatch("Test");
try {
$test = new QueryExamples();
$test->getTexts();
} catch (Error $e) {
Errors::showCatch($e);
}
unset($test);
I've got an autoloader setup already. I'll include the code of that if anyone wants it. The next bit is a file called errors.php which is called by the try, catch and, depending on how the configuration file for the framework is setup, shows the message on the screen and/or sends it to a log file:
class Errors{
static function showCatch($errMessage){
// If manual errors are turned on in the config file.
if(Config::$config['defaults']['manErrors'] == 1){
// Show the error message.
echo "<br />{$errMessage}<br />";
}
// Log the error.
Logs::logManError($errMessage);
die();
}
}
How and where it is logged in the file is handled by another static function in another document:
class Logs{
static function logManError($errMessage) {
// If custom error logging is turned on in the config file:
if (Config::$config['defaults']['customErrorsLogging'] == 1) {
// Get the file path from the config file.
$manErrors_file = Config::$config['paths']['customErrors'];
// Format the error message.
$logTxt = "New Custom Error - [".date("d/m/Y - H:i:s")."]\n".$errMessage."\n\n";
file_put_contents($manErrors_file, $logTxt, FILE_APPEND);
}
}
}
The output in the log file:
New Custom Error - [23/03/2020 - 01:50:17]
Error: (Error message)
New Custom Error - [23/03/2020 - 01:50:17]
Error: (Error message)
I changed the error message to try and find where the errors were being called:
// Format the error message.
// $logTxt = "New Custom Error - [".date("d/m/Y - H:i:s")."]\n".$errMessage."\n\n";
$logTxt = debug_backtrace()["0"]['file']." ".debug_backtrace()['0']['line']."\n".debug_backtrace()['1']['file']." ".debug_backtrace()['1']['line']."\n\n";
The output in the log file:
F:\xampp\htdocs\FRED 0.0.0\classes\errors.php 21
F:\xampp\htdocs\FRED 0.0.0\index.php 22
F:\xampp\htdocs\FRED 0.0.0\classes\errors.php 21
F:\xampp\htdocs\FRED 0.0.0\index.php 22
errors.php:21 is where I called the the Logs:logManError() static function and index.php:22 is where I called the Errors:showCatch() function in the try, catch block.
I also tried adding a global variable to index.php to check how many times the showCatch() function was being called:
(index.php)
$GLOBALS['i'] = 0;
(errors.php)
$GLOBALS['i'] += 1;
// Log the error.
Logs::logManError($errMessage."<br />".$GLOBALS['i']);
die();
The output:
New Custom Error - [23/03/2020 - 01:50:17]
Error: (Error message)
1
New Custom Error - [23/03/2020 - 01:50:17]
Error: (Error message)
1
Okay. Here is the answer. After doing more research there appears to be nothing wrong with my code. It seems that it's something to do with the rewrite engine combined with a few other things. I've included a link to the page that gave me the solution.
https://www.sitepoint.com/community/t/duplicate-entries-with-file-put-contents-when-rewriteengine-on/16188/11
Related
I am using the PHP copy function in part of my program, where the parameters of the function depend on user input. I am trying to avoid the default php error message if they include a path that the function cannot use, and output a custom message like shown below. I am new to handling errors/ exceptions. I am still getting the php default error message instead of the custom 'Path was incorrect!' using the method below.
What I tried:
try{
copy($webImagePath, $destinationPath);
}
catch(Exception $e){
echo 'Path was incorrect!';
}
Consider set_error_handler: http://php.net/manual/en/function.set-error-handler.php
Example:
set_error_handler("someFunction");
function someFunction($errno, $errstr) {
output details and information
}
You should have thrown an Exception with custom message you wished to display.
You can either suppress the default PHP error message for individual statements by preceding them with an '#' symbol. Or you might change error_reporting level per page( check this link for more details:http://php.net/manual/en/function.error-reporting.php
Also check the folowing code snippet
$file='example.txt'; //replace the file name with your URL
$newfile = 'example.txt.bak';
try{
$ret=#copy($file, $newfile);
if (!$ret){
throw new Exception("File path doesn't exist..");
}
}
catch(Exception $e){
echo $e->getMessage();
}
I am unable to execute a code inside catch block when there is a file exception. Below is the code.
try {
// Check for file size. which will make sure file exists in local server.
filesize($localPath);
return 'success';
}catch(FileException $e) {
Log::error('Error reading file size ' . $e->getMessage());
$failedAttempts = $failedAttempts + 1;
// Set to sleep for 10.
sleep(10);
// Start recursive call.
$this->downloadMedia($url, $localPath, $failedAttempts);
}
I also tried \Exception and \ErrorException but nothing worked. Any help is appreciated.
if You check this manual You'll see filesize method does not throw exception.
Returns the size of the file in bytes, or FALSE
(and generates an error of level E_WARNING) in case of an error.
and since looks like You've not enabled error reporting or display_error directive - You don't see that E_WARNING
You can just throw exception manually:
try {
// Check for file existence or throw exception.
if (!is_file($localPath)) {
throw new Exception($localPath.' does not exists');
}
return 'success';
}
catch(Exception $e) {
// here goes exception handling
}
Extra advice (out of question's scope):
There is no logic to check for file existence in recurring way.
If file is downloaded it will exist otherwise You'll never download it during recursion.
What if someone will pass link to file that does not exists?
Better jus download it and stop with success or exception.
I'd like to write errors about r/w permissions of /protected/runtime directory into apache error log and do not throw any exception into interface. What i should do to resolve my 'problem'?
Thank you and sorry for my english!
the problem was resolved by using:
error_log($message);
and removing CException calls when script is trying to check runtime folder or run file_put_contents function
When debug is off yii is displaying this error using (by default) site/error view, just change it to not display message text and display something generic (ex if code == 500 then display "Internal Error")
If you want to have error in apache log I see only a bit unclean way, anyway just tested and it works. Set display_errors = Off and log_errors = On in php.ini and then change action that handles errors from yii to restore default handlers and rise error again - it should result in log record in apache log and blank screen in browser, ex:
public function actionError() {
if (($error=Yii::app()->errorHandler->error)) {
if (strpos($error['message'], 'runtime') !== false) {
restore_error_handler();
restore_exception_handler();
user_error("Problem with runtime: " . $error['message'], E_USER_ERROR);
exit();
}
if(Yii::app()->request->isAjaxRequest) {
echo $error['message'];
} else {
$this->render('error', $error);
}
}
}
I am using the PHP copy function in part of my program, where the parameters of the function depend on user input. I am trying to avoid the default php error message if they include a path that the function cannot use, and output a custom message like shown below. I am new to handling errors/ exceptions. I am still getting the php default error message instead of the custom 'Path was incorrect!' using the method below.
What I tried:
try{
copy($webImagePath, $destinationPath);
}
catch(Exception $e){
echo 'Path was incorrect!';
}
Consider set_error_handler: http://php.net/manual/en/function.set-error-handler.php
Example:
set_error_handler("someFunction");
function someFunction($errno, $errstr) {
output details and information
}
You should have thrown an Exception with custom message you wished to display.
You can either suppress the default PHP error message for individual statements by preceding them with an '#' symbol. Or you might change error_reporting level per page( check this link for more details:http://php.net/manual/en/function.error-reporting.php
Also check the folowing code snippet
$file='example.txt'; //replace the file name with your URL
$newfile = 'example.txt.bak';
try{
$ret=#copy($file, $newfile);
if (!$ret){
throw new Exception("File path doesn't exist..");
}
}
catch(Exception $e){
echo $e->getMessage();
}
I am trying to replace the built in php shutdown_function with a custom one.
It works perfectly, however, it still outputs the original error (built in error) above my new error message.
<?php
function shutdown_output() {
$error = error_get_last();
if($error !== NULL) {
echo "ERROR";
exit();
} else {
echo "NO ERROR";
}
}
// Set the error reporting:
register_shutdown_function('shutdown_output');
// test.php does not exist, just here to get a critical error
require_once("test.php");
?>
Any ideas?
As already mentioned in comments, the use of register_shutdown_function is not going to override built-in error handling (the same way that set_error_handler doesn't either).
If you don't want to see the original message, disable the output of them in your php.ini using display_errors = 0. Or on the fly in your script using ini_set('display_errors', 0);.