0

I'm a beginner in PHP OOP and I'm with some doubts about the correct way of handling errors in PHP.

Look at this function for example:

public function deleteFileFromDisk($fileNameToBeDeleted) {

    $handle = unlink($fileNameToBeDeleted);

    if (!$handle) {
        $result = "(this->deleteFileFromDisk) - Error, " . $fileNameToBeDeleted . " not deleted.";
    } else {
        $result = "(this->deleteFileFromDisk) - Success, " . $fileNameToBeDeleted . " deleted.";
    }
    return $result;
}

Is this the correct way of doing it, or I can do better than this?

Let me add some details of what I'm achieving...

I'm running class methods, and I need to control errors in the process. If any call to the object throw an error I need to catch it and send an e-mail.

Here are the object interactions:

$testar_classe = new geoIpImportCSV('geolitecity', 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCity_CSV/');
$testar_classe->downloadAndSaveFile('./', $testar_classe->obtainDownloadFileName());
$testar_classe->uncompressZipFile($testar_classe->obtainDownloadFileName(), '.');
$testar_classe->deleteLine(1, 'GeoLiteCity-Location.csv');               
$testar_classe->deleteLine(1, 'GeoLiteCity-Blocks.csv');
$testar_classe->deleteDataFromTable('tabela1');
$testar_classe->deleteDataFromTable('tabela2');
$testar_classe->insertLinesToDb('GeoLiteCity-Location.csv', 'tabela1');
$testar_classe->insertLinesToDb('GeoLiteCity-Blocks.csv', 'tabela2');
$testar_classe->deleteFileFromDisk($testar_classe->obtainDownloadFileName());
$testar_classe->deleteFileFromDisk('GeoLiteCity-Blocks.csv');
$testar_classe->deleteFileFromDisk('GeoLiteCity-Location.csv'); 

Which is the best way of handle this? Create a new method to take care of the exceptions? There are any examples on how to do this?

Best Regards.

André
  • 24,706
  • 43
  • 121
  • 178
  • possible duplicate of [PHP Error handling](http://stackoverflow.com/questions/1081061/php-error-handling) – ircmaxell Dec 22 '10 at 14:12
  • That's bloatware, not error handling. why not to leave it just `unlink($fileNameToBeDeleted);`? **What exactly you want to handle here and wat for?** – Your Common Sense Dec 22 '10 at 14:15
  • 1
    Oh, @JMC that would be incredible stupid. – Your Common Sense Dec 22 '10 at 14:17
  • The `@` character is evil and should be destroyed! – ircmaxell Dec 22 '10 at 14:20
  • I was thinking in terms of front-end display code, not OOP. Is `@` so bad then too? – JakeParis Dec 22 '10 at 14:25
  • @JMC it is ALWAIS bad. there is not a single reason to suppress an error message. Error messages are your friends. One should be keen to see them. While gagging them is suicide. – Your Common Sense Dec 22 '10 at 14:29
  • @JMC - As for the front end display code - are you going to say that you will set @ at the EVERY operator in the code, or what? – Your Common Sense Dec 22 '10 at 14:39
  • @Col. Shrap - No of course not, just in cases where I don't care script-wise if the function failed, I just want to know what to display to the user. Example: attempted delete of file which didn't exist, so `unlink()` failed. Why run `if(file_exists()) unlink());` when @unlink is much simpler in that case. And I'm not saying this is how it should be done, I'm just trying to learn from you. – JakeParis Dec 22 '10 at 14:49
  • @JMC see, you just take this operator wrong. It doesnt just prevent an error message from displaying, but eliminates it absolutely! You won't even see it in the error log (as you should). So, id you want to prevent an error from displaying - make it properly, with `display_errors=0` setting. As for the file_exists - it's indeed terrible case. there can be nearly thousand reasons for the error beside just absense of the file. So, you throw them all away at once. And turn debugging into nightmare. – Your Common Sense Dec 22 '10 at 15:08
  • @JMC you cannot ve more wrong with your `when @unlink is much simpler`. These things cannot be interchenged! Error message is to help you to locate a problem. while if(file_exists() is to avoid intentional error. You MUST use both. `if(file_exists()) unlink());` is the ONLY possible way. It wont reise an error for the absent file, BUT will notify you of all the other errors, such as permission ones – Your Common Sense Dec 22 '10 at 15:16
  • @Col. - Point taken. Thanks for the good conv. – JakeParis Dec 22 '10 at 15:30
  • Andre My answer code is personally developed by me through rough studies from books of error handling. I wont care of votes. Try my code. i will works perfect even inside frameworks. – Mohan Ram Dec 23 '10 at 07:48

6 Answers6

2

What you are doing here (returning a string as a success/failure indicator) is really a bad idea. The problem is that strings such as this are only good for presenting to humans; they are absolutely useless to your code when it needs to know if there was a failure and if so, how to handle it.

Read these related questions:

Community
  • 1
  • 1
Jon
  • 428,835
  • 81
  • 738
  • 806
2

Try looking at exceptions:

public function deleteFileFromDisk($fileNameToBeDeleted) {

    $handle = unlink($fileNameToBeDeleted);

    if (!$handle) {
        throw new Exception("(this->deleteFileFromDisk) - Error, " . $fileNameToBeDeleted . " not deleted.";
    } 
}

And then in code:

try {
    $object->deleteFileFromDisk('blabla');
}
catch (Exception $e) {
    echo $e->message;
}
Silver Light
  • 44,202
  • 36
  • 123
  • 164
2

That method would probably create some headaches for you. For example, what if you wanted to programmatically detect if the function had succeeded? strpos() for "Error" or "Success"? Some alternatives:

  1. Return boolean true/false for simple success/failure cases.
  2. Throw exceptions or trigger_error() when something goes wrong.
  3. Return a special error container class, a la WP_Error, and check to see if the return value of the function is an instance of this class.
Annika Backstrom
  • 13,937
  • 6
  • 46
  • 52
1

In OOP fashion, error handling is mostly done with exceptions. Exceptions should be thrown in exceptional cases, namely when a procedure or routine cannot proceed further if a condition was not met, or if an unexpected scenario has occured.

In your above example, exceptions are not necessary. However, returning a string containing a message that says if it works or not is bad, because it requires the user of the method to parse that string to determine whether or not it worked.

There are two possible outcomes in your method: it worked (true), or it didn't (false). Since your method just deletes a file from disk and do not proceed further, returning a boolean would be just fine.

The routine that uses deleteFromDisk then could throw an exception if the deletion of the file is mandatory in its workflow:

$file = 'foo/bar.txt';
if (!$this->deleteFromDisk($file)) {
   throw new Exception('Directory could not be removed: cannot delete '.$file.' from disk');
}

rmdir('foo/');

In the above example, the deletion of the file is mandatory for the next statement to work, so using exceptions is correct.

netcoder
  • 66,435
  • 19
  • 125
  • 142
0

I'd advice looking into concept of exceptions in PHP. It makes code much clearer and it's more powerful than if..else statements everywhere.

In your specific case, I'd just throw exception in your function if deleting of file fails and then use it in try..catch statement somewhere else.

Ondrej Slinták
  • 31,386
  • 20
  • 94
  • 126
-1

Create sample folder and save my below codes as error.php and create folder error inside sample create empty txt file errorlog.txt

<?php
function error_msg($err_type,$err_msg,$err_file,$err_line)
{
$fh=fopen("error/errorlog.txt","a");
$date1=date("Y-m-d H:i:s");
$er="
===============================================================================================================
"."
Error: Type: ".$err_type."Message: ".$err_msg."ErrorFile: ".$err_file."Errorline: ".$err_line."Time: ".$date1.
"
===============================================================================================================
";
fwrite($fh,$er);
fclose($fh);
}

//set_error_handler("error_msg");
function handler($err_type,$err_msg,$err_file,$err_line)
{
    switch($err_type)
    {
        //fatal error
    case E_ERROR:
        $fh=fopen("error/errorlog.txt","a");
        $date1=date("Y-m-d H:i:s");
        $er="
        ===============================================================================================================
        "."
        Error: Type: ".$err_type."Message: ".$err_msg."ErrorFile: ".$err_file."Errorline: ".$err_line."Time: ".$date1.
        "
        ===============================================================================================================
        ";
        fwrite($fh,$er);
        fclose($fh);
        break;
        //warnings
    case E_WARNING:
        $fh=fopen("error/errorlog.txt","a");
        $date1=date("Y-m-d H:i:s");
        $er="
        ===============================================================================================================
        "."
        Error: Type: ".$err_type."Message: ".$err_msg."ErrorFile: ".$err_file."Errorline: ".$err_line."Time: ".$date1.
        "
        ===============================================================================================================
        ";
        fwrite($fh,$er);
        fclose($fh);
        break;
        //notices
    case E_NOTICE:
        //
        break;

    }
}

set_error_handler("handler");
?>
Mohan Ram
  • 8,345
  • 25
  • 81
  • 130
  • Hi, thanks for your reply. There are an example how how to use this two functions? Best Regards. – André Dec 22 '10 at 14:33
  • just use include "sample/error.php"; in your pages since function call also is in my script just include it. I had written two functions. use any one of them. – Mohan Ram Dec 22 '10 at 14:39
  • another bloatware example. get rid of this ridiculous code. And then just set up `log_errors` and `error_log` directives. – Your Common Sense Dec 22 '10 at 15:10