PHP unlink() handling the exception

前端 未结 7 1097
南旧
南旧 2020-12-15 15:48

Well, I have been wondering if I can handle the unlink() function properly. I dont want the unlink() function to throw some nasty error if it is un

相关标签:
7条回答
  • 2020-12-15 16:25

    This method may seem strange but I believe it is the most foolproof one, it accounts for "race conditions".

    • mkdir-race-condition
    • file_put_contents-race-condition

    is_file

    if(is_file($file) && @unlink($file)){
        // delete success
    } else if (is_file ($file)) {
        // unlink failed.
        // you would have got an error if it wasn't suppressed
    } else {
      // file doesn't exist
    }
    

    Why?

    Firstly is_file is the correct method to check if a FILE exists not file_exists. file_exists checks for both directories and files so may return the TRUE for a directory with the same filename, you cannot remove a directory with unlink and doing so will throw an error.

    Checking a file exists(is_file) before you unlink is the correct/best way to delete a file.

    if(is_file($file) && unlink($file)){
    

    But it is not a foolproof method as it is common for a file to be deleted in the small window between the is_file check and the unlink. I have experianced this several times when a caching method uses the filesystem.

    But it is best method available.

    So you can do everything right and still get an error!

    Well at least the error tells you if it fails....well actually you can tell if it fails without the error

    unlink

    Returns TRUE on success or FALSE on failure.

    If you have coded it correctly and can differentiate between a success and failed unlink then YES suppress the error, it does not benifit you or your code.

    Whether the error is suppressed or not, This is the best method i can think of to prevent it from happening. By reducing the time between the check and the delete you will reduce the likeliness of it throwing an error.

    EDIT: updated link URLs

    0 讨论(0)
  • 2020-12-15 16:28

    Handling "Resource Unavailable" error by unlink() as Exception using try catch

    Even is_file() or file_exists() will check for file is exists or not, there are chances that file is being used by some applications that will prevent deletion and unlink() will display "Resource Unavailable" error.

    So after trying many methods like: is_resource(), is_writable(), stream_get_meta_data()...etc, I reached the only best way to handle error while "deleting" a file that is either not exists or is exists but being used by some application

    function delete_file($pFilename)
    {
        if ( file_exists($pFilename) ) { 
            //  Added by muhammad.begawala@gmail.com
            //  '@' will stop displaying "Resource Unavailable" error because of file is open some where.
            //  'unlink($pFilename) !== true' will check if file is deleted successfully.
            //  Throwing exception so that we can handle error easily instead of displaying to users.
            if( @unlink($pFilename) !== true )
                throw new Exception('Could not delete file: ' . $pFilename . ' Please close all applications that are using it.');
        }   
        return true;
    }
    

    === USAGE ===

    try {
        if( delete_file('hello_world.xlsx') === true )
            echo 'File Deleted';
    }
    catch (Exception $e) {
        echo $e->getMessage(); // will print Exception message defined above.
    }
    
    0 讨论(0)
  • 2020-12-15 16:31

    You can use is_writable to test whether you have proper permissions to modify or delete a file.

    http://php.net/manual/en/function.is-writable.php

    try {
      if(!is_writable($file))
          throw new Exception('File not writable');
    
      unlink($file);
    }
    catch(Exception $e) { /* do what you want */ }
    
    0 讨论(0)
  • 2020-12-15 16:43

    Use PHP_Exceptionizer https://github.com/DmitryKoterov/php_exceptionizer/blob/master/lib/PHP/Exceptionizer.php

    $exceptionizer = new PHP_Exceptionizer(E_ALL);
    try {
            unlink($file)
        }  catch (E_WARNING $e) {
            return false;
        }
    
    0 讨论(0)
  • 2020-12-15 16:46

    My experience says that calling file_exists() just before calling unlink() does NOT work, even if clearstatcache() was called just before calling file_exists().

    There are many combinations of PHP versions and operating systems and the only way that I have found that always works (that is, avoids showing the warning message in case of error) is making my own function silent_unlink():

    function silent_unlink( $filename )
    {
      $old_er = error_reporting();
      error_reporting( $old_er & ~E_WARNING );
      $result = unlink( $filename );
      error_reporting( $old_er );
      return $result;
    }
    

    It disables the error reporting of warnings just for calling unlink() and restores the previous error_reporting() status.

    0 讨论(0)
  • 2020-12-15 16:48

    unlink doesn't throw exceptions, in generates errors. The proper way to do this is check that the file exists before trying to call unlink on it. If you are merely worried about not having the errors output then you should just turn off display_errors which you should always do in a production environment anyway. Then they will just be logged.

    Do not suppress errors with the @, its rarely advisable.

    Can you be more descriptive about @

    Im not sure what you mean exactly. But the documentation is here. As far as why you don't want to use it... That is because then you never know that code isn't working or is problematic. Even if the code still works from a functional perspective it's still got an issue and that issue could potentially make something else completely not work at some point. If you never have the error you'll probably waste a lot of time debugging.

    Its fine to change your log level or disable the display of errors, but you never want to completely suppress them.

    0 讨论(0)
提交回复
热议问题