2

Because of PHP's unlink() not supporting exceptions natively, I'm making a wrapper function for it. It should throw a FileNotFoundException if, well, the given file could not be deleted because it doesn't exist.

For this, I need to determine whether the error thrown by unlink() was caused by a missing file or something else.

This is my test version for a custom delete function:

public function deleteFile($path){
    set_error_handler(function($errLevel, $errString){
        debug($errLevel);
        debug($errString);
    });
    unlink($path);
    restore_error_handler();
}

For $errLevel and $errString I get 2 (E_WARNING) and unlink(/tmp/fooNonExisting): No such file or directory

A rather bold approach would be like this:

if( strpos($errString, 'No such file or directory') !== false ) {
    throw new FileNotFoundException();
};

Question 1: How much can I rely on the error string being the same across different PHP versions? Question 2: Is there a much better way?

pixelistik
  • 7,541
  • 3
  • 32
  • 42

4 Answers4

2

I would simplify the code:

public function deleteFile($path){

    if (!file_exists($path) {
        throw new FileNotFoundException();
    }else{
        unlink($path);
    }

    if (file_exists($path) {
        throw new FileNotDeleted();
    }
}

Then you don't have to catch the $errstr and do complicated error catching. And it will work down to PHP 4 when exceptions were introduced.

pixelistik
  • 7,541
  • 3
  • 32
  • 42
powtac
  • 40,542
  • 28
  • 115
  • 170
  • 1
    Yes, good solution. But this will bury all other types of problems, too, like wrong file permissions. I'd rather only convert "file not found" into an exception. – pixelistik Jun 05 '12 at 15:22
  • I modified your solution (review pending), with `unlink()` in an `else` block we can get rid of the bad `@` part. I'll probably use this technique, but let's wait what other answers are coming about the initial error handling/identification issue. – pixelistik Jun 05 '12 at 15:38
  • Choosing this answer as correct, even though it does not teach me lots of details about PHP error handlers. But it points in a *simple* direction, which I was also asking for. – pixelistik Jun 06 '12 at 06:27
  • For PHP error "magic" have a look at http://php.net/manual/function.error-get-last.php and http://php.net/manual/reserved.variables.phperrormsg.php – powtac Jun 06 '12 at 11:56
1

While reading trough my old questions I came across the ErrorException, combined with set_error_handler() this would be a automatic Error to Exception transformer for all native PHP errors:

function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");

/* Trigger exception */
unlink('Does not exitsts'); 

Can anybody prof this?

Community
  • 1
  • 1
powtac
  • 40,542
  • 28
  • 115
  • 170
  • 1
    It won't work for every error. Beside parser-time and startup errors, some other runtime errors, as fatal errors, are not catch by any error handler. – ABu Jul 30 '14 at 08:41
0

I believe it(i.e. your code) should be portable enough as it is... As regards a better way to achieve the same thing, i would do things differently (although the code is simple, it's also more readable...so bear with me)

function deleteFile($file_path){
    if(!is_file($file_path)){
        throw new Exception("The path does not seem to point to a valid file");
    }
    if(!file_exists($file_path)){
        throw new Exception("File not found!");
    }
    if(unlink($file_path)){
        return true;
    } else {
        throw new Exception("File deletion failed!");
    }
}

Of course you can always compress and improve on the code...hop this helps!

Emmanuel Okeke
  • 1,452
  • 15
  • 18
0

I've seen php error messages change quite a bit over the years. Maybe, try to detect a change in the last error over a very granular piece of code, and then result to string parsing in a very loose manor.

$lastErr = error_get_last();
unlink($file);
if ($lastErr !== error_get_last()) {
    // do something
    //maybe string parsing and/or testing with file_exists, is_writable etc...
}
goat
  • 31,486
  • 7
  • 73
  • 96