23

I'm writing a script in PHP5 that requires the code of certain files. When A file is not available for inclusion, first a warning and then a fatal error are thrown. I'd like to print an own error message, when it was not possible to include the code. Is it possible to execute one last command, if requeire did not work? the following did not work:

require('fileERROR.php5') or die("Unable to load configuration file.");

Supressing all error messages using error_reporting(0) only gives a white screen, not using error_reporting gives the PHP-Errors, which I don't want to show.

maček
  • 73,409
  • 36
  • 162
  • 195
R_User
  • 9,932
  • 23
  • 73
  • 118

6 Answers6

27

You can accomplish this by using set_error_handler in conjunction with ErrorException.

The example from the ErrorException page is:

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

/* Trigger exception */
strpos();
?>

Once you have errors being handled as exceptions you can do something like:

<?php
try {
    include 'fileERROR.php5';
} catch (ErrorException $ex) {
    echo "Unable to load configuration file.";
    // you can exit or die here if you prefer - also you can log your error,
    // or any other steps you wish to take
}
?>
trejder
  • 16,472
  • 26
  • 116
  • 210
Sjan Evardsson
  • 404
  • 4
  • 4
  • @SajnEvardsson php manual has ErrorException third parameter as $errno, not the second one. – Basit Jan 23 '13 at 21:52
  • 2
    The example above is copied directly from the ErrorException docs (link above) - in the "official" example they use $errno as $code, while others (including in the comments on that page) have suggested using it as $severity - note that if you like you can use it for both, or neither. – Sjan Evardsson Jan 29 '13 at 17:35
  • Seems like overly-engineered way of doing very simple thing – Jacek Dziurdzikowski Jun 04 '20 at 21:45
  • This is actually a useful solution in my situation. i have legacy (pre-framework!) code that has suffixes in filenames... `ClassA.class.php` or `InterfaceA.interface.php`. Long term goal: fix all that. Short term: reduce redundant file-exists checks by attempting both safely. – cautionbug May 23 '22 at 15:31
21

I just use 'file_exists()':

if (file_exists("must_have.php")) {
    require "must_have.php";
}
else {
    echo "Please try back in five minutes...\n";
}
  • 1
    Better to use [is_readable()](http://www.php.net/is_readable); it checks for file existence, in addition of readability of the file (simply, a file must exist to be readable). Also, to prevent from including directories, you should use [is_dir()](http://www.php.net/is_dir) (i.e. !is_dir($filename)). – MAChitgarha Jul 02 '18 at 18:21
  • `file_exists` doesn't check include path so it may not work – Dan Stevens Dec 10 '19 at 18:00
  • incldue `die()` at the end of your echo. `require` will stop the script from running and if the file does not exist the echo will be shown and the rest of the page load. But instead addng `die()` at the will show nothing in the page other than the message. – Dexter Jan 30 '20 at 13:47
  • It also works with DIRECTORIES, not only files, which is even better – Mbotet Mar 17 '21 at 08:56
4

A better approach would be to use realpath on the path first. realpath will return false if the file does not exist.

$filename = realpath(getcwd() . "/fileERROR.php5");
$filename && return require($filename);
trigger_error("Could not find file {$filename}", E_USER_ERROR);

You could even create your own require function in your app's namespace that wraps PHP's require function

namespace app;

function require_safe($filename) {
  $path = realpath(getcwd() . $filename);
  $path && return require($path);
  trigger_error("Could not find file {$path}", E_USER_ERROR);
}

Now you can use it anywhere in your files

namespace app;

require_safe("fileERROR.php5");
maček
  • 73,409
  • 36
  • 162
  • 195
  • I have absolutely no idea why, but your code does not work correctly (produces false positive), when run in PHP CLI / console. I.e. It halts execution of script, claiming, that file XYZ does not exists, while it actually does exists -- commenting out your code and going directly to `include()` works fine and file is included without errors. – trejder May 08 '15 at 06:56
2

A simple way I am using is that

<?php
    ...
    if(!include 'config.php'){
        die("File not found handler. >_<");
    }
   ...
?>
Prashant
  • 372
  • 1
  • 6
  • 17
2

I would suggest you took a look at the most recent comment in the documentation for the set_error_handler() function.

It suggests the following as a method (and with an example) of catching fatal errors:

<?php
function shutdown()
{
    $a=error_get_last();
    if($a==null)  
        echo "No errors";
    else
         print_r($a);

}
register_shutdown_function('shutdown');
ini_set('max_execution_time',1 );
sleep(3);
?> 

I haven't tried the suggestion, but this could propably be used in other fatal error scenarios.

Repox
  • 14,674
  • 7
  • 53
  • 76
  • While this may work, it produces good question, if this will work in conditions, OP is asking? I believe that most people landing here are looking for a solution, where they can catch `require` on non-existing file **and continue** script execution. Being able to gracefully die (i.e. display something, I want but end up with script termination even so -- and that is what your code seems to be doing) doesn't seem to be fitting into many scenarios. I assume, script can display whatever it want's if it going to die. I want to prevent die / termination on non-existing file fed to `require`. – trejder May 08 '15 at 06:59
1

You need to use include(). Require(), when used on non-existent file, produces a fatal error and exits the script, so your die() won't happen. Include() only throws warning and then the script continues.

Ondra Koupil
  • 952
  • 5
  • 8
  • Your answer is either specific to a certain PHP version or specific to certain `php.ini` configuration. On my side (PHP 5.5.4) with my configuration, changing `require` to `include` brings absolutely no difference. Both are throwing ugly fatal errors, that I can't catch. – trejder May 08 '15 at 06:47