29

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
  • 76,434
  • 37
  • 167
  • 198
R_User
  • 10,682
  • 25
  • 79
  • 120

7 Answers7

32

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
  • 17,148
  • 27
  • 124
  • 216
Sjan Evardsson
  • 454
  • 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
25

I just use 'file_exists()':

if (file_exists("must_have.php")) {
    require "must_have.php";
}
else {
    echo "Please try back in five minutes...\n";
}
  • 2
    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
  • 76,434
  • 37
  • 167
  • 198
  • 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

As of PHP 7.0, you can catch the Throwable exception thrown by require().

try {
    require '/path/not-found/or-not-available.php';
}
catch (Error $e) {
    // debugging example:
    die('Caught error => ' . $e->getMessage());
}

Will output something like:

Caught error => Failed opening required '/path/not-found/or-not-available.php' [...]

Syscall
  • 19,327
  • 10
  • 37
  • 52
2

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
  • 1,034
  • 6
  • 9
  • 1
    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
  • @trejder - This is not correct Include throws a warning, but it carries on. It is not fatal. Whereas require throws an error and the program will stop. It is true that both produce entries in `error.log` – Rohit Gupta Jul 30 '22 at 04:53
  • @RohitGupta You are referring to my seven years old comment that talks about things 100% configuration specific. Are you sure that it is not possible to configure PHP the way that I describe? I don't know what was my PHP's configuration seven years ago, but I pretty much don't see a reason for which I would be writing here something that is not true. I rather think that I wrote what I was observing at that time and how my environment was actually behaving. – trejder Jul 30 '22 at 05:59
1

A simple way I am using is that

<?php
    ...
    if(!include 'config.php'){
        die("File not found handler. >_<");
    }
   ...
?>
Prashant
  • 394
  • 1
  • 6
  • 18
  • any specific instance where this won't work? – ShifraSec Nov 20 '21 at 00:18
  • I have downvoted you because this still generates a warning. Execution still carries on, but it leaves two lines in your error log. It is still an error condition, that you have not caught. – Rohit Gupta Jul 30 '22 at 04:51
1

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
  • 15,015
  • 8
  • 54
  • 79
  • 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