When using filesystem functions, what would be the correct way of handling errors such as:
Warning: symlink(): No such file or directory in /path-to-script/symlink.php on line XXX
My usual approach is to check for any condition that could produce an error before calling the filesystem function. But if the command fails for a reason I haven't foreseen, how can I catch the error to show the user a more helpful message?
This is a simplification of the code that creates the symbolic link:
$filename = 'some-file.ext';
$source_path = '/full/path/to/source/dir/';
$dest_path = '/full/path/to/destination/dir/';
if(file_exists($source_path . $filename)) {
if(is_dir($dest_path)) {
if( ! file_exists($dest_path . $filename)) {
if (symlink($source_path . $filename, $dest_path . $filename)) {
echo 'Success';
} else {
echo 'Error';
}
}
else {
if (is_link($dest_path . $filename)) {
$current_source_path = readlink($dest_path . $filename);
if ( $current_source_path == $source_path . $filename) {
echo 'Link exists';
} else {
echo "Link exists but points to: {$current_source_path}";
}
} else {
echo "{$source_path}{$filename} exists but it is not a link";
}
}
} else {
echo "{$source_path} is not a dir or doesn't exist";
}
} else {
echo "{$source_path}{$filename} doesn't exist";
}
Followup / Solutions
As sugested by Sander, using set_error_handler()
to turn errors and warnings into exceptions.
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");
try {
symlink($source_path . $filename, $dest_path . $filename);
echo 'Success';
}
catch (ErrorException $ex) {
echo "There was an error linking {$source_path}{$filename} to {$dest_path}{$filename}: {$ex->getMessage()}";
}
restore_error_handler();
Using the @ operator is another solution (although some suggest avoiding it whenever possible):
if (@symlink($source_path . $filename, $dest_path . $filename)) {
echo 'Success';
} else {
$symlink_error = error_get_last();
echo "There was an error linking {$source_path}{$filename} to {$dest_path}{$filename}: {$symlink_error['message']}";
}
I think you want to want to set an errorhandler which throws exceptions:
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
// see http://php.net/manual/en/class.errorexception.php
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");
Then your code would be:
try {
symlink(); // when an error occured, it jumps to the catch
} catch (ErrorException $ex) {
// do stuff with $ex
}
I suggest using Fileysystem component that is widely used and tested solution for filesystem operations https://github.com/symfony/Filesystem/blob/master/Filesystem.php#L248
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With